【问题标题】:conditional rendering in styled components样式化组件中的条件渲染
【发布时间】:2018-07-08 05:31:48
【问题描述】:

如何在样式组件中使用条件渲染来使用 React 中的样式组件将我的按钮类设置为活动?

在 css 中我会这样做:

<button className={this.state.active && 'active'}
      onClick={ () => this.setState({active: !this.state.active}) }>Click me</button>

在样式化的组件中,如果我尝试在类名中使用“&&”,它不喜欢它。

import React from 'react'
import styled from 'styled-components'

const Tab = styled.button`
  width: 100%;
  outline: 0;
  border: 0;
  height: 100%;
  justify-content: center;
  align-items: center;
  line-height: 0.2;
`

export default class Hello extends React.Component {
  constructor() {
    super()
    this.state = {
      active: false
    }  
    this.handleButton = this.handleButton.bind(this)
}

  handleButton() {
    this.setState({ active: true })
  }

  render() {
     return(
       <div>
         <Tab onClick={this.handleButton}></Tab>
       </div>
     )
  }}

【问题讨论】:

    标签: reactjs styled-components


    【解决方案1】:

    通过有条件地应用它们,似乎也可以使用类名:

    const BoxClassname = styled.div.attrs((props) => ({
      className: clsx(props.$primary && "primary")
    }))`
      background: #000;
      height: 1px;
      width: 50px;
      &.primary {
        background: pink;
      }
    `;
    
    /*
    // You could also use a second component instead of .attrs
    export const BoxClassname = (props) => {
      return (
        <BoxClassnameWrapper
          className={clsx(props.$primary && "primary")}
          {...props}
        />
      );
    };
    */
    

    我喜欢这种语法的一点是不要过多地混合 JS 和 CSS。

    限制是它看起来更慢,请参阅this demo code sandbox 以获得性能比较。我真的不明白为什么:/因为逻辑上。

    我在阅读Josh Comeau take on using CSS variables in Styled Components后产生了这个想法。

    • CSS 变量让您配置...变量(切换颜色等)
    • 从逻辑上讲,classNames + CSS 选择器让您定义条件

    毕竟,这个逻辑已经存在于 CSS 中,className 已经是用来处理条件渲染的了。 Styled Components 有助于保持样式干净隔离并处理高级场景,但我不喜欢它过多地干预样式。

    【讨论】:

      【解决方案2】:

      我还没有见过这种语法,我觉得当你需要使一个完整的块条件时最干净:

      const StyledButton = styled(button)`
          display: flex;
          background-color: white;
      
          ${props => !props.disabled} {
              &:hover {
                  background-color: red;
              }
      
              &:active {
                  background-color: blue;
              }
          }
      `;
      

      因此无需关闭/打开刻度即可使其正常工作。

      【讨论】:

      • 我喜欢这种语法,但你确定它适用于非布尔检查吗? (例如 props => props.foo === "bar")似乎对我检查特定值不起作用
      • 它的工作原理是因为我经常使用这种语法。您可能需要在其中放置一个 console.log 以检查“foo”是否已实际定义。
      • 您能详细说明一下吗?我不明白它为什么起作用,这是否特定于样式化组件的工作原理?
      • 是的,我确认 TS 在我尝试执行以下操作时会抱怨:${(props) =&gt; props.$isSelected} { ...
      【解决方案3】:

      在您的示例中我没有注意到任何 &&,但是对于样式组件中的条件渲染,您可以执行以下操作:

      // Props are component props that are passed using <StyledYourComponent prop1="A" prop2="B"> etc
      const StyledYourComponent = styled(YourComponent)`
        background: ${props => props.active ? 'darkred' : 'limegreen'}
      `
      

      在上面的例子中,当 StyledYourComponent 使用 active 属性渲染时背景会变暗,如果没有提供 active 属性或者它是假的 Styled-components 会自动为你生成类名:)

      如果要添加多个样式属性,则必须使用从 styled-components 导入的 css 标签:

      在您的示例中我没有注意到任何 &&,但是对于样式组件中的条件渲染,您可以执行以下操作:

      import styled, { css } from 'styled-components'
      // Props are component props that are passed using <StyledYourComponent prop1="A" prop2="B"> etc
      const StyledYourComponent = styled(YourComponent)`
        ${props => props.active && css`
           background: darkred; 
           border: 1px solid limegreen;`
        }
      `
      

      或者您也可以使用 object 来传递样式,但请记住 CSS 属性应该是驼峰式:

      import styled from 'styled-components'
      // Props are component props that are passed using <StyledYourComponent prop1="A" prop2="B"> etc
      const StyledYourComponent = styled(YourComponent)`
        ${props => props.active && ({
           background: 'darkred',
           border: '1px solid limegreen',
           borderRadius: '25px'
        })
      `
      

      【讨论】:

      【解决方案4】:

      这是一个使用 TypeScript 的简单示例:

      import * as React from 'react';
      import { FunctionComponent } from 'react';
      import styled, { css } from 'styled-components';
      
      interface IProps {
        isProcessing?: boolean;
        isDisabled?: boolean;
        onClick?: () => void;
      }
      
      const StyledButton = styled.button<IProps>`
        width: 10rem;
        height: 4rem;
        cursor: pointer;
        color: rgb(255, 255, 255);
        background-color: rgb(0, 0, 0);
      
        &:hover {
          background-color: rgba(0, 0, 0, 0.75);
        }
      
        ${({ disabled }) =>
          disabled &&
          css`
            opacity: 0.5;
            cursor: not-allowed;
          `}
      
        ${({ isProcessing }) =>
          isProcessing &&
          css`
            opacity: 0.5;
            cursor: progress;
          `}
      `;
      
      export const Button: FunctionComponent<IProps> = ({
        children,
        onClick,
        isProcessing,
      }) => {
        return (
          <StyledButton
            type="button"
            onClick={onClick}
            disabled={isDisabled}
            isProcessing={isProcessing}
          >
            {!isProcessing ? children : <Spinner />}
          </StyledButton>
        );
      };
      
      <Button isProcessing={this.state.isProcessing} onClick={this.handleClick}>Save</Button>
      

      【讨论】:

        【解决方案5】:

        如果你的状态是这样在你的类组件中定义的:

        class Card extends Component {
          state = {
            toggled: false
          };
          render(){
            return(
              <CardStyles toggled={this.state.toggled}>
                <small>I'm black text</small>
                <p>I will be rendered green</p>
              </CardStyles>
            )
          }
        }
        

        使用基于该状态的三元运算符定义样式组件

        const CardStyles = styled.div`
          p {
            color: ${props => (props.toggled ? "red" : "green")};
          }
        `
        

        它应该将这里的 &lt;p&gt; 标记呈现为绿色。

        这是一种非常时髦的造型方式

        【讨论】:

          【解决方案6】:

          你可以这样做

          <Tab active={this.state.active} onClick={this.handleButton}></Tab>
          

          在你的风格中是这样的:

          const Tab = styled.button`
            width: 100%;
            outline: 0;
            border: 0;
            height: 100%;
            justify-content: center;
            align-items: center;
            line-height: 0.2;
          
            ${({ active }) => active && `
              background: blue;
            `}
          `;
          

          【讨论】:

          • 在 TypeScript 中,您需要使用 ({ active }: any)withProps
          • 它在 CSS 字符串中添加了一个false 会导致麻烦
          • @LucasWillems 如果您使用过时的 babel 转译器并做出反应。 React 不再呈现虚假值
          • 条件代码不应包含在普通的反引号中,而应包含在css``
          猜你喜欢
          • 2019-02-24
          • 2020-12-08
          • 2020-08-23
          • 1970-01-01
          • 1970-01-01
          • 2020-12-22
          • 2022-01-27
          • 2018-09-10
          • 2021-06-07
          相关资源
          最近更新 更多