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>
);
}
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?
CodePudding user response:
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.
CodePudding user response:
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