简体   繁体   中英

How to pass React props from parent to child using composition pattern

As stated here , a good way to pass properties to child component is via composition pattern. My problem is that I need to pass props from several component to the same child, with the maximum de-couplication:

export default function App() {
  const foo = true;

  return (
    <div className="App">
      <Parent>
        <Child foo={foo} />
      </Parent>
    </div>
  );
}

function Parent(props) {
  function methodA() {
    return true;
  }

  // return <div>I'm the parent! {props.children(methodA)}</div>; // <-- gives me error!
  return <div>I'm the parent! {props.children}</div>;
}

function Child(props) {
  return (
    <div>
      I'm the child!
      <br />
      App pass me foo: {props.foo.toString()}
      <br />
      Parent pass methodA: {/*props.methodA().toString()<-- gives me error!*/}
    </div>
  );
}

Demo

As you can see, I've got no problem to pass values from my top one to the lowest, or from the middle one to the lower, but I cannot achieve a way to do both the same time, using the children props to keep thing de-coupled.

Is that possible in some way?

I am not sure if the above pattern can strictly be called composition . The way I see it, composition would involve App passing Child as props to the Parent component and Parent does not modify Child in any way. But that might be a technicality.

Anyway, the problem here seems to be that you cannot pass methodA to the Child component. One way to solve this is to clone the Child element in the Parent component and add your props to it. So, your new Parent component would look something like:

function Parent(props) {
  function methodA() {
    return true;
  }
  const NewChild = React.cloneElement(props.children);
  return <div>I'm the parent! <NewChild methodA={methodA} /></div>;
}

You can read more about cloneElement here .

From the ReactJS docs :

Remember that components may accept arbitrary props, including primitive values, React elements, or functions.

You could make Parent 's children prop a function.

export default function App() {
  const foo = true;

  return (
    <div className="App">
      <Parent>{(methodA) => <Child foo={foo} methodA={methodA} />}</Parent>
    </div>
  );
}

function Parent(props) {
  function methodA() {
    return true;
  }

  return <div>I'm the parent! {props.children(methodA)}</div>;
}

function Child(props) {
  return (
    <div>
      I'm the child!
      <br />
      App pass me foo: {props.foo.toString()}
      <br />
      Parent pass methodA: {props.methodA().toString()}
    </div>
  );
}

https://codesandbox.io/s/recursing-northcutt-2om3o?file=/src/App.js

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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