【问题标题】:How to access child's props from parent's styled-component?如何从父样式组件访问子道具?
【发布时间】:2019-09-05 10:32:07
【问题描述】:

我有这样的结构:

  <Wrapper activeTextColor="red">
    <Text active={true}>Text 1</Text>
    <Text active={false}>Text 2</Text>
  </Wrapper>

样式化组件应如下所示:

const Text = styled.p``;

const Wrapper = styled.div`
  ${Text} {
    ${props =>
      props.activeTextColor &&
      css`
        /* How to make color red based on "active" attribute of Text element? */
      `}
  }
`;

如何在此处从父样式组件访问子属性?

这是live example

【问题讨论】:

  • 你不会这样做吧?您将制作一个包含此样式组件的真实组件,并使用它将正确的道具传递给孩子
  • @CallumLinington 一针见血。我什至不确定您尝试做的事情是否可行,因为它完全违背了样式化组件的观点(因为该组件不再只是一个组件)。

标签: javascript css reactjs frontend styled-components


【解决方案1】:

你不能(据我所知)。但是您可以从子组件访问父组件(反之亦然)。这似乎完成了你想要做的事情。

简答:

你必须将 parent prop 传递给子组件

在父组件&lt;Wrapper /&gt; 中,您必须克隆您的子组件并将activeTextColor 传递给子组件:

const StyledWrapper = styled.div``;

class Wrapper extends React.Component {
  render() {
    const { children, activeTextColor } = this.props;
    return (
     <StyledWrapper activeTextColor={activeTextColor}>
       {React.Children.map(children, child =>
         React.cloneElement(child, {
           activeTextColor: activeTextColor
         })
       )}
     </StyledWrapper>
    );
  }
}

activeTextColoractive 现在都可以从 Text 组件访问。

const Text = styled.p`
  ${props => css`
    color: ${props.active ? activeTextColor : "#000"};
  `}
`;

另一种选择:

在上述情况下,使用 ThemeProvider/ThemeConsumer 可能更有意义。如果您知道activeTextColor 将变为红色(也许您正在处理设计标记),那么使用以下命令访问活动颜色:

${props => css`
  background: ${props.active ? props.theme.activeTextColor : '#000'};
`}

详细解答以及为什么有人要这样做):

这扩展了上面的简短答案。在某些时候,您可能需要访问父组件中的父道具,以及子组件中的子道具和父道具。

现实世界的例子是 Tabs 之类的。我有两种不同的样式/选项卡变体,Tabs 容器组件和Tab 都需要自己的样式,具体取决于其自己的道具。它是一个组件,有两种不同的样式。

嵌套样式组件将不起作用。所以你最终会得到这样的结果。


const StyledTabs = styled.div`
  display: flex;
  justify-content: flex-start;
  ${props =>
    props.variant === "wizard" &&
    css`
      justify-content: space-between;
    `}
`;

const StyledTab = styled.p`
  font-size: 14px;
  white-space: nowrap;
  font-family: sans-serif;
  border: 1px solid #ddd;
  padding: 15px;
  ${props => css`
    background: ${props.active ? "#fff" : "#f6f6f6"};
  `}

  ${props =>
    props.variant === "box" &&
    css`
      & {
        border-right: 0 none;
        &:last-child {
          border-right: 1px solid #ddd;
        }
        border-top: ${props.active
          ? "2px solid lightseagreen"
          : "1px solid #ddd"};
        border-bottom: ${props.active ? "none" : "1px solid #ddd"};
      }
    `}

  ${props =>
    props.variant === "wizard" &&
    css`
      & {
        margin-right: 20px;
        text-align: center;
        line-height: 40px;
        height: 40px;
        width: 40px;
        border-radius: 50%;
        color: ${props.active ? "#fff" : "#000"};
        ${props.active && "background: lightseagreen"};
      }
    `}
`;

class Tabs extends React.Component {
  render() {
    const { children, variant } = this.props;
    return (
      <StyledTabs variant={variant}>
        {React.Children.map(children, child =>
          React.cloneElement(child, {
            variant: variant
          })
        )}
      </StyledTabs>
    );
  }
}

class Tab extends React.Component {
  render() {
    const { children, variant, active } = this.props;
    return (
      <StyledTab variant={variant} active={active}>
        {children}
      </StyledTab>
    );
  }
}

const App = () => (
  <div>
    <Tabs variant="box">
      <Tab active={true}>Tab 1</Tab>
      <Tab>Tab 2</Tab>
      <Tab>Tab 3</Tab>
    </Tabs>
    <Tabs variant="wizard">
      <Tab active={true}>Step 1</Tab>
      <Tab>Step 2</Tab>
      <Tab>Step 3</Tab>
    </Tabs>
  </div>
);

render(<App />, document.getElementById("root"));

完整示例: https://codesandbox.io/s/upbeat-thunder-wfo2m

styled-component 的 GitHub 上的相关问题: https://github.com/styled-components/styled-components/issues/1193

StackOverflow上有不少相关的问题,但我认为没有多少明确的答案: react-native with styled-components parent prop How to style a child component from a parent styled component, considering passed props

【讨论】:

  • 似乎是最相关的答案。谢谢!
【解决方案2】:
const Text = styled.p`color: ${props => props.active ? "red" : "palevioletred"};`;

【讨论】:

  • 如果您编辑此答案以解释为什么它是正确的以及为什么它是该问题的最佳答案,那么这个答案会更有帮助,以便其他人可以从您的知识中学习。
猜你喜欢
  • 2022-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多