简体   繁体   English

React — 使用 styled-components 传递 props

[英]React — Passing props with styled-components

I just read in the styled-components documentation that the following is wrong and it will affect render times.我刚刚在styled-components文档中读到以下内容是错误的,它会影响渲染时间。 If that is the case, how can I refactor the code and use the required props to create a dynamic style?如果是这样,我该如何重构代码并使用所需的道具来创建动态样式?

Thank you in advance.先感谢您。

Tab component选项卡组件

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

I believe what the documentation is saying is that you should avoid including your styles inside of the rendering component:我相信文档所说的是你应该避免在渲染组件中包含你的样式:

DO THIS做这个

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

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

INSTEAD OF THIS取而代之的是

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

  return <StyledWrapper>{message}</StyledWrapper>
}

Because what happens is when the component's Props changes, then the component will re-render and the style will regenerate.因为当组件的 Props 发生变化时,组件会重新渲染,样式会重新生成。 Therefore it makes sense to keep it separate.因此,将其分开是有意义的。

So if you read further on to the Adapting based on props section, they explain this:因此,如果您进一步阅读基于道具的改编部分,他们会解释这一点:

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

// }

this works because when you use the Button component in class X, it will know the props of class X without you having to tell it anything.这是有效的,因为当您在 X 类中使用Button组件时,它会知道 X 类的道具,而无需您告诉它任何内容。

For your scenario, I imagine the solution would be simply:对于您的情况,我想解决方案很简单:

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>

I haven't tested this at all, so please feel free to try it out and let me know if it works for you or whatever worked for you!我根本没有测试过这个,所以请随意尝试一下,让我知道它是否适合您或任何适合您的方法!

You can pass an argument with Typescript as follows:您可以使用 Typescript 传递参数,如下所示:

<StyledPaper open={open} />    

...

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

Another way to do it would be另一种方法是

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

This way you are type-safe in terms of the props you want to send into the styled component.这样,就要发送到样式组件的道具而言,您是类型安全的。 (Good when coding in Typescript) (在打字稿中编码时很好)

For a more simple example with functional components:有关功能组件的更简单示例:

Suppose you have an arrow like polygon and you need 2 of them pointing in different directions.假设你有一个像多边形的箭头,你需要其中 2 个指向不同的方向。 So you can pass the rotate value by props所以你可以通过道具传递旋转值

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

Then in the Component Arrow you have to pass the props like normal component to the styled component but in the styled component you have to use it like props:然后在组件箭头中,您必须像普通组件一样将道具传递给样式化组件,但在样式化组件中,您必须像道具一样使用它:

    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;
           

If you're using Typescript create an interface inside your styles file!如果您使用的是 Typescript,请在​​样式文件中创建一个界面! Otherwise, you won't be able to access props in your CSS否则,您将无法访问 CSS 中的道具

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

And don`t forget to declare the props you want to use in your CSS inside your JSX并且不要忘记在 JSX 中的 CSS 中声明要使用的道具

interface TabProps{
  text: string;
}

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


}

Consider styled components documentation gives example of using reacts context api [2] for different themes.考虑样式化组件文档提供了针对不同主题使用 reacts context api [2] 的示例。

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

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

Exporting styled-component导出样式组件

Button按钮

and passing scrollPosition as a prop in functional component并将scrollPosition作为功能组件中的道具传递

PassingPropsToSyledComponent传递PropsToSyledComponent

import styledComponents from "styled-components";
            
export const Button = styledComponents.div`
       position: ${ props => props.scrollPosition ? 'relative' : 'static' };
`;
export const PassingPropsToSyledComponent = ()=> {
   return(
   <Button scrollPosition={scrollPosition}>
       Your Text Here
   </Button>
   )
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM