样式化组件中的条件渲染

Posted

技术标签:

【中文标题】样式化组件中的条件渲染【英文标题】: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>
     )
  

【问题讨论】:

【参考方案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'
  )
`

【讨论】:

css - ??。我不知道那件事。它在文档中的什么位置? @CodeFinity 它在那里:styled-components.com/docs/api#css【参考方案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;
  `
`;

【讨论】:

文档:Adapting based on props. 在 TypeScript 中,您需要使用 ( active : any) 或 withProps。 它在 CSS 字符串中添加了一个false 会导致麻烦 @LucasWillems 如果您使用过时的 babel 转译器并做出反应。 React 不再呈现虚假值 条件代码不应包含在普通的反引号中,而应包含在css``

以上是关于样式化组件中的条件渲染的主要内容,如果未能解决你的问题,请参考以下文章

样式化组件 + 故事书:当我传递新样式时,SVG 图标不会重新渲染

使用 MUI 和样式化组件重新渲染的次数过多

如何将样式化组件作为属性添加到 TypeScript 中的另一个样式化组件?

样式化组件中的动态主题

ReactReact全家桶组件+组件三大核心属性state-props-refs+事件处理与条件渲染+列表与表单+状态提升与组合+高阶函数与函数+函数柯里化

ReactReact全家桶组件+组件三大核心属性state-props-refs+事件处理与条件渲染+列表与表单+状态提升与组合+高阶函数与函数+函数柯里化