【问题标题】:React styled-components style a dynamic componentReact styled-components 为动态组件设置样式
【发布时间】:2021-11-04 16:07:33
【问题描述】:

我有以下问题:

我在我的项目中定义了一些图标。每个图标都由一个组件类型(来自 Material-UI 的图标)加上一些额外的道具定义。我就是这样做的,所以我可以用不同的方式渲染这些图标。

无论如何,假设我想在 2 个地方重复使用相同的图标,但在一个地方我希望它是红色的,在另一个地方我希望它是绿色的。 MUI 图标不接受颜色道具(我的意思不是 RGB 图标,只是一些预定义的颜色)。所以这样做的方法是用css(color:)设置图标组件的样式。

我使用styled-components,所以我通常这样做的方式是:

const StyledIcon = styled(AssignmentIcon)`
  color: red
`

但问题是,在某些地方我不知道我会设计哪个图标。例如,某些组件可能会收到带有AssignmentIcons 和BugReportIcons 的列表。与 styled-components 一样,我无法在另一个组件中定义样式化的组件 - 所以我无法创建像上面那样的样式,而只是将图标从道具传递给它。

我是这样解决的:https://codesandbox.io/s/nostalgic-hofstadter-ww2ly。基本上,我有一个styleIcon 函数,它接受React.ComponentType(当然是动态的),放入styled() 并返回它。这样我就为图标应用了一些样式,现在我可以渲染它了。

我的问题是:这似乎有点粗略,有一些辅助功能来完成这项工作。有没有更简单的方法来做到这一点? (顺便说一句,我在渲染图标时不能使用 style={{}} 道具 - 它可能会与我通过道具传播应用的其他样式发生冲突)

【问题讨论】:

    标签: javascript css reactjs styled-components


    【解决方案1】:

    根据您的问题,我假设您想在没有明确样式的情况下从 Material UI 更改颜色。所以我想出了一个将 Material UI 图标作为一个子节点的包装器。

    首先,我们需要为该包装器创建样式:

    const StyledIcon = styled.span<{color: string}>`
      svg, .icon {
        color: ${props => props.color}; // You can even pass a hex color
      }
    `
    

    其次,创建一个单独的 React 组件。您可以单独使用样式化的组件,但这将有助于您在未来处理状态和效果:

    interface ColorfulIconProps {
      color: string;
    
      [k: string]: any;
    }
    
    const ColorfulIcon: React.FC<ColorfulIconProps> = ({ color, children, ...rest }) => {
      // States and effects
    
      return (
        <StyledIcon color={color} {...rest}>
          {children}
        </StyledIcon>
      );
    };
    

    最后,要使用它,只需传递您想要的任何 Material UI 图标,或您自己的图标集,只要它们的格式为 svg

    const App = () => {
      return (
        <ColorfulIcon color="red">
          <AMaterialUIIcon />
        </ColorfulIcon>
      );
    };
    

    现场演示: https://codesandbox.io/s/modern-brook-oecgn?file=/src/StyledIcon.tsx

    【讨论】:

    • 好的,这可行,但请参阅this comment,我认为这对我来说是一个更简单的解决方案
    【解决方案2】:

    您的组件应该始终能够切换到不同的颜色。

      const color = props => props.color || 'red'
    
      const StyledIcon = styled.div`
        color: ${color};
      `
    

    如果给出color,则使用color,例如

      return <StyledIcon color="blue" />
    

    我不知道这是否能解决您的问题。有时我们想使用主题模式,例如StyledComponent 确实支持主题。

    https://styled-components.com/docs/advanced

    即使您不想总是使用一个主题,也可以在运行时应用不同的主题。

      <ThemeProvider theme={theme1}>
        // A
        <ThemeProvider theme={theme2}>
          // B
          <Button>Themed</Button>
        </ThemeProvider>
        // C
      </ThemeProvider>
      // D
    

    位置 A、B、C、D 有不同的主题:

    • A.主题1
    • 乙。主题2
    • C.主题1
    • D.默认主题

    我相信基本解决方案应该能给你一些想法,但如果没有,试试 StyledComponent 提供的这个复杂的主题选项。

    【讨论】:

    • 是的,但是你错过了一个重要的事实,我不是试图动态修改 div,我试图将某些属性“附加”到一个类型/类。例如,我有一个来自 MUI 的类型 AssignmentIcon。或者可能是我创建的FooIcon。我想要做的是能够在渲染时/在渲染时为其添加一些新属性 - 不使用 style prop ,使用 SC。我所做的是当我收到这样的类型并且我有另一个像 StyledIcon 这样包含 css 样式的类型时,我只写:&lt;StyledIcon as={icon} /&gt; 其中 icon 是一个动态变量。这样css就被应用到icon
    • 使用cloneElement 然后reactjs.org/docs/react-api.html#cloneelementcloneElement(render, { additionalProps }).
    猜你喜欢
    • 2018-10-20
    • 1970-01-01
    • 2023-03-26
    • 2021-07-16
    • 2018-11-12
    • 2018-08-21
    • 1970-01-01
    • 2020-05-01
    • 2021-08-26
    相关资源
    最近更新 更多