React — 使用 styled-components 传递 props

Posted

技术标签:

【中文标题】React — 使用 styled-components 传递 props【英文标题】:React — Passing props with styled-components 【发布时间】:2019-02-18 15:37:37 【问题描述】:

我刚刚在styled-components documentation 中读到以下内容是错误的,它会影响渲染时间。如果是这样,我该如何重构代码并使用所需的道具来创建动态样式?

提前谢谢你。

标签组件

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

const Tab = ( onClick, isSelected, children ) => 
    const TabWrapper = styled.li`
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 100px;
    margin: 1px;
    font-size: 3em;
    color: $props => (isSelected ? `white` : `black`);
    background-color: $props => (isSelected ? `black` : `#C4C4C4`);
    cursor: $props => (isSelected ? 'default' : `pointer`);
`

    return <TabWrapper onClick=onClick>children</TabWrapper>



export default Tab

【问题讨论】:

【参考方案1】:

我相信文档所说的是你应该避免在渲染组件中包含你的样式:

这样做

const StyledWrapper = styled.div`
  /* ... */
`

const Wrapper = ( message ) => 
  return <StyledWrapper>message</StyledWrapper>

取而代之

const Wrapper = ( message ) => 
  // WARNING: THIS IS VERY VERY BAD AND SLOW, DO NOT DO THIS!!!
  const StyledWrapper = styled.div`
    /* ... */
  `

  return <StyledWrapper>message</StyledWrapper>

因为当组件的 Props 发生变化时,组件会重新渲染,样式会重新生成。因此,将其分开是有意义的。

因此,如果您进一步阅读基于道具改编部分,他们会解释:

const Button = styled.button`
  /* Adapt the colours based on primary prop */
  background: $props => props.primary ? "palevioletred" : "white";
  color: $props => props.primary ? "white" : "palevioletred";

  font-size: 1em;
  margin: 1em;
  padding: 0.25em 1em;
  border: 2px solid palevioletred;
  border-radius: 3px;
`;

// class X extends React.Component 
//  ...

render(
  <div>
    <Button>Normal</Button>
    <Button primary>Primary</Button>
  </div>
);

// 

这是因为当你在 class X 中使用 Button 组件时,它会知道 class X 的 props 而无需你告诉它任何事情。

对于您的情况,我想解决方案很简单:

const TabWrapper = styled.li`
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 100px;
  margin: 1px;
  font-size: 3em;
  color: $props => (props.isSelected ? `white` : `black`);
  background-color: $props => (props.isSelected ? `black` : `#C4C4C4`);
  cursor: $props => (props.isSelected ? 'default' : `pointer`);
`;

const Tab = ( onClick, isSelected, children ) => 
  return <TabWrapper onClick=onClick>children</TabWrapper>


const X = <Tab onClick=() => console.log('clicked') isSelected>Some Children</Tab>

我根本没有测试过这个,所以请随意尝试一下,让我知道它是否适合你或任何适合你的方法!

【讨论】:

这对我有帮助。【参考方案2】:

您可以使用 Typescript 传递参数,如下所示:

<StyledPaper open=open />    

...

const StyledPaper = styled(Paper)< open: boolean >`
   top: $p => (p.open ? 0 : 100)%;
`;

【讨论】:

【参考方案3】:

另一种方法是

const StyledDiv = styled.div.attrs((props: color: string) => props)`
    width: 100%;
    height: 100%;
    background-color: $(props) => props.color;
`

//...

render() 
    return (
        <StyledDiv color="black">content...</StyledDiv>
    );

这样,就要发送到样式组件的道具而言,您是类型安全的。 (在 Typescript 中编码时很好)

【讨论】:

这是一个很好的解决方案,因为它遵循最佳实践并为我工作 感谢您添加此类型安全性,非常有帮助!【参考方案4】:

如果您使用的是 Typescript,请在​​样式文件中创建一个界面! 否则,您将无法访问 CSS 中的 props

import styled from 'styled-components'

interface StyledLiProps
  selected: boolean


export const TabWrapper = styled.li`
    
// styles ...

color: $props => (selected ? `white` : `black`);
background-color: $props => (selected ? `black` : `#C4C4C4`);
`

别忘了在你的 JSX 中声明你想在 CSS 中使用的 props

interface TabProps
  text: string;


const Tab = ( text : TabProps) => 
 
//...
  
return <TabWrapper selected=isSelected onClick=() => updateTab>text</TabWrapper>



【讨论】:

【参考方案5】:

关于功能组件的更简单示例:

假设您有一个像多边形一样的箭头,并且您需要其中 2 个指向不同的方向。所以可以通过 props 传递旋转值

               <Arrow rotates='none'/>
          
               <Arrow rotates='180deg'/>

然后在组件箭头中,您必须像普通组件一样将道具传递给样式组件,但在样式组件中您必须像道具一样使用它:

    import React from 'react';
    import styled from "@emotion/styled";

    const ArrowStyled = styled.div`
      background-color: rgba(255,255,255,0.9);
      width: 24px;
      height: 30px;
      clip-path: polygon(56% 40%,40% 50%,55% 63%,55% 93%,0% 50%,56% 9%);
      transform: rotate($props => props.rotates);
     `


const Arrow = (rotates) => 
    return (
       <ArrowStyled rotates=rotates/>
    );


export default Arrow;
           

【讨论】:

【参考方案6】:

考虑样式化组件文档提供了针对不同主题使用 reacts context api [2] 的示例。

[1]https://www.styled-components.com/docs/advanced

[2]https://reactjs.org/docs/context.html

【讨论】:

以上是关于React — 使用 styled-components 传递 props的主要内容,如果未能解决你的问题,请参考以下文章

在 react-native 中使用 styled-components 不会覆盖样式

nextjs + react-native-web + styled-components :warnOnce

在 react 中使用 react-router 4 和 styled-component 时,不应在 Router 外部使用 Route 或 withRouter()

使用 React && styled-components 中的 State 从两个不同的按钮触发侧边栏

使用 Styled-Components 在 React Bootstrap 中覆盖嵌套样式

无法使用 styled-components 将样式应用于 React Native 中的自定义组件?