How to pass props to {this.props.children}
Cloning children with new props
You can use React.Children
to iterate over the children, and then clone each element with new props (shallow merged) using React.cloneElement
. For example:
const Child = ({ doSomething, value }) => ( <button onClick={() => doSomething(value)}>Click Me</button>);function Parent({ children }) { function doSomething(value) { console.log("doSomething called by child with value:", value); } const childrenWithProps = React.Children.map(children, child => { // Checking isValidElement is the safe way and avoids a typescript // error too. if (React.isValidElement(child)) { return React.cloneElement(child, { doSomething }); } return child; }); return <div>{childrenWithProps}</div>}function App() { return ( <Parent> <Child value={1} /> <Child value={2} /> </Parent> );}ReactDOM.render(<App />, document.getElementById("container"));
<script src="https://unpkg.com/react@17/umd/react.production.min.js"></script><script src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script><div id="container"></div>
Calling children as a function
Alternatively, you can pass props to children with render props. In this approach, the children (which can be children
or any other prop name) is a function which can accept any arguments you want to pass and returns the children:
const Child = ({ doSomething, value }) => ( <button onClick={() => doSomething(value)}>Click Me</button>);function Parent({ children }) { function doSomething(value) { console.log("doSomething called by child with value:", value); } // Note that children is called as a function and we can pass args to it. return <div>{children(doSomething)}</div>}function App() { // doSomething is the arg we passed in Parent, which // we now pass through to Child. return ( <Parent> {doSomething => ( <React.Fragment> <Child doSomething={doSomething} value={1} /> <Child doSomething={doSomething} value={2} /> </React.Fragment> )} </Parent> );}ReactDOM.render(<App />, document.getElementById("container"));
<script src="https://unpkg.com/react@17/umd/react.production.min.js"></script><script src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script><div id="container"></div>
Instead of <React.Fragment>
or simply <>
you can also return an array if you prefer.
For a slightly cleaner way to do it, try:
<div> {React.cloneElement(this.props.children, { loggedIn: this.state.loggedIn })}</div>
Edit:To use with multiple individual children (the child must itself be a component) you can do. Tested in 16.8.6
<div> {React.cloneElement(this.props.children[0], { loggedIn: true, testPropB: true })} {React.cloneElement(this.props.children[1], { loggedIn: true, testPropA: false })}</div>
Try this
<div>{React.cloneElement(this.props.children, {...this.props})}</div>
It worked for me using react-15.1.
Use {...this.props}
is suggested in https://reactjs.org/docs/jsx-in-depth.html#spread-attributes