如何从父母的样式组件访问孩子的道具?

时间:2019-09-05 10:32:07

标签: javascript css reactjs frontend styled-components

我有这种结构:

  <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

2 个答案:

答案 0 :(得分:1)

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

简短答案:

您必须将父属性传递给子组件

在父组件<Wrapper />中,您必须克隆孩子并将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>
    );
  }
}

activeTextColor组件现在可以访问activeText

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

另一个选项:

在上述情况下,使用ThemeProvider / ThemeConsumer可能更有意义。如果您知道activeTextColor将是红色的(也许您正在处理设计令牌),请使用以下方法访问活动颜色:

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

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

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

一个真实的例子就是Tabs之类的东西。我有两种不同的Tab样式/变体,Tabs容器组件和Tab都需要根据自己的道具使用自己的样式。它是一个用两种不同方式设置样式的组件。

Tab Example

嵌套样式化的组件无效。因此,您最终会遇到这样的事情。


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

答案 1 :(得分:0)

const Text = styled.p颜色:$ {props => props.active吗? “ red”:“ palevioletred”}; ;