使用 React JS 中的样式组件,添加条件样式的更优选方法是什么?

With styled-components in React JS, what is the more preferred way to add conditional styling?

示例代码(代码示例来自 Learning React,第 146-150 页);

请注意,与两年前写的书不同,我正在尝试使用样式化组件实现相同的功能。在书中,CSS 全部在 app.css 内部完成,Star 组件如下所示:

const Star = ({ selected=false, onClick= f=>f }) =>
  <StyledStar className={(selected) ? "selected star" : "star"}
    onClick={onClick}>
  </StyledStar> 

和 app.css 看起来像这样:

.star {
  display: inline;
  cursor: pointer;
  height: 25px;
  width: 25px;
  margin: 2px;
  float: left;
  background-color: grey;
  clip-path: polygon(
          50% 0%,
          63% 38%,
          100% 38%,
          69% 59%,
          82% 100%,
          50% 75%,
          18% 100%,
          31% 59%,
          0% 38%,
          37% 38%
      );
}



.star.selected {
  background-color: red;
}

如您所见,如果选择了星星,它将显示为红色而不是灰色。

我想使用样式组件重构它,这是我尝试过的方法:

// star.js

import React from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'

const StyledStar = styled.div`
  display: inline;
  cursor: pointer;
  height: 25px;
  width: 25px;
  margin: 2px;
  float: left;
  background-color: ${`this.props.selected ? 'grey' : 'red'`};
  clip-path: polygon(
          50% 0%,
          63% 38%,
          100% 38%,
          69% 59%,
          82% 100%,
          50% 75%,
          18% 100%,
          31% 59%,
          0% 38%,
          37% 38%
  );
`

const Star = ({ selected=false, onClick= f=>f }) =>
  <StyledStar className={(selected) ? "selected" : ""}
    onClick={onClick}>
  </StyledStar>

Star.propTypes = {
  selected: PropTypes.bool,
  onClick: PropTypes.func
}

export default Star

出于某种原因,我在 background-color: ${`this.props.selected ? 'grey' : 'red'`}; 中期望的插值不起作用,我的三元条件出现在 CSS 中,正如我在 JavaScript 中写的那样。

我错过了什么吗?我认为可以像这样在样式 div 内部进行插值,但我想不是吗?

我也试过这个

const StyledStar = styled.div`
  display: inline;
  cursor: pointer;
  height: 25px;
  width: 25px;
  margin: 2px;
  float: left;
  background-color: grey;
  clip-path: polygon(
          50% 0%,
          63% 38%,
          100% 38%,
          69% 59%,
          82% 100%,
          50% 75%,
          18% 100%,
          31% 59%,
          0% 38%,
          37% 38%
  );

  .selected {
    background-color: red;
  }

...但我也无法让它工作。 (与我熟悉的 SCSS 不同,您无法在样式块中看到 'nest' 您的 CSS 声明,不是吗?)

在带样式的组件中,传递给插值的函数是使用 props 调用的。您可以解构 props 以获得 selected:

const StyledStar = styled.div`
  display: inline;
  cursor: pointer;
  height: 25px;
  width: 25px;
  margin: 2px;
  float: left;
  background-color: ${({ selected }) => selected ? 'grey' : 'red'};
  clip-path: polygon(
          50% 0%,
          63% 38%,
          100% 38%,
          69% 59%,
          82% 100%,
          50% 75%,
          18% 100%,
          31% 59%,
          0% 38%,
          37% 38%
  );
`

用法 - 以与传递相同的方式将 prop 传递给样式组件 onClick:

const Star = ({ selected = false, onClick = f => f }) => (
  <StyledStar
    selected={selected}
    onClick={onClick}>
  </StyledStar>
)

直接引用样式组件文档:

Interpolation: This can either be a string or a function. Strings are combined with the rules as-is. Functions will receive the styled component's props as the first and only argument.

您的组件的插值应该是一个函数:

const StyledStar = styled.div`
  display: inline;
  cursor: pointer;
  height: 25px;
  width: 25px;
  margin: 2px;
  float: left;
  background-color: ${props => props.selected ? 'grey' : 'red'};
`

或者,您可以通过在顶层传递函数来使它更清晰:

const StyledStar = styled.div(
  props => `
  /* props can be accessed from the above props */
  color: ${props.color};
  background: ${props.selected ? 'grey' : 'red'};
`
)

demo

编辑:修正错别字