将道具传递给孩子们的孩子(嵌套组件树)

时间:2018-12-13 14:04:04

标签: javascript reactjs

我不确定这是否可行,但这是我想在Reactjs中实现的目标:

<Comp1>
  <Comp2 />
  <Comp3>
    <Comp4 />
  </Comp3>
</Comp1>

所以我想做的是,我想使用React.cloneElement APIComp1组件向Comp4组件注入道具。 这样,如果我想传播一个道具或一组道具以使其成为层次结构中第6级的孩子,我应该能够做到。

但是我现在设法达到的目标是,将道具注射给直系孩子,而不是孩子的孩子。

这是我的努力:https://codesandbox.io/s/x2q06l5z64

我想我已经把问题弄清楚了,如果有混淆,您可以将其解决。

3 个答案:

答案 0 :(得分:1)

您的三元逻辑颠倒了。

您原来的代码是

return childzFurtherChildren
      ? React.cloneElement(child, { ...newProps, hello: true })
      : React.cloneElement(child, { ...newProps, hello: true }, childzFurtherChildren);

但必须是

return childzFurtherChildren
      ? React.cloneElement(child, { ...newProps, hello: true }, childzFurtherChildren)
      : React.cloneElement(child, { ...newProps, hello: true });

因为当您有更多子代(已处理过的 )时,您需要将其添加到克隆的元素中。

https://codesandbox.io/s/8n26lq6mj9上的演示已更新

答案 1 :(得分:0)

这是React的context API的经典用例。

const MyContext = React.createContext('');

class Parent extends React.Component {
  render() {
    const { message } = this.props;
    return (
      <MyContext.Provider value={message}>
        {this.props.children}
      </MyContext.Provider>
    )
  }
}

class Child extends React.Component {
  render() {
    return (
      <MyContext.Consumer>
        {(message) => (
          <div style={{ border: '1px solid #ccc' }}>
            <h3>Child</h3>
            {message}
          </div>
        )}
      </MyContext.Consumer>
    )
  }
}

class App extends React.Component {
  state = { message: 'default message' }
  handleChange = ({ target }) => this.setState({ message: target.value })
  render() {
    const { message } = this.state;
    return (
      <div className="App">
        <input value={message} onChange={this.handleChange} />
        <Parent message={message}>
          <div className="some-child">
            <div className="some-child">
              <div className="some-child">
                <div className="some-child">
                  <Child />
                </div>
              </div>
            </div>
          </div>
        </Parent>
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"/>

答案 2 :(得分:0)

  

更新:在本示例中,我使用的不是HOC,React称之为HOC,   不确定此类代码的正确名称。范围组件   也许。附带说明一下,文档中给出HOC的原因,例如。 (代码重用)。现在可以使用Hooks做得更好。

扩展HOC(高阶组件)概念。

这是一个简单的例子。

请注意,Comp4不必从Comp2和Comp3传递道具,这是因为我们已经将Comp1变成了HOC。因此,尽管可以使用Context,但理想的情况是可以使用HOC。这是因为每个组件始终可以被隔离对待,这使得调试的可重用性变得更好。

function Comp2(props) {
  return <div>Comp2: <br/>{props.children}</div>
}

function Comp3(props) {
  return <div>Comp3: <br/>{props.children}</div>
}

function Comp4(props) {
  return <div>Comp4: {props.value}<br/>{props.children}</div>
}

function Comp1(props) {
 return <div>
  Comp1: {props.value}
  <Comp2>
    <Comp3>
      <Comp4 value={props.value}/>
    </Comp3>
  </Comp2>
 </div>
}



ReactDOM.render(
  <Comp1 value={"This get passed to everything using a HOC"}/>,
  document.querySelector("#mount")
);
div {
  margin-left: 1em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="mount"/>