React —通过样式组件传递道具

时间:2018-09-13 20:42:20

标签: javascript reactjs styled-components

我刚刚在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

6 个答案:

答案 0 :(得分:8)

我相信文档中所说的是,您应该避免将样式包含在呈现组件中:

这样做

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>
);

// }

之所以可行,是因为当您在X类中使用 Button 组件时,它将无需知道任何内容就能知道X类的道具。

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

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>

我根本没有测试过,所以请随时尝试一下,让我知道它是否对您有用或对您有用!

答案 1 :(得分:3)

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

假设您有一个类似多边形的箭头,并且需要其中 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;
           

答案 2 :(得分:3)

如果您使用的是 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>


}

答案 3 :(得分:2)

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

<StyledPaper open={open} />    

...

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

答案 4 :(得分:1)

考虑者风格的组件文档给出了针对不同主题使用reacts上下文api [2]的示例。

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

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

答案 5 :(得分:1)

另一种方法是

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 编码时很好)