Stas Kurilin Stas Kurilin - 3 months ago 24
Javascript Question

Passing props to generic children

Is there way to pass props to a generic child (not a component that you know ahead)?

Something that would make

Wrapper
be able to pass
foo
to children.

var Wrapper = React.createClass({
render: function () {
return <div>
{this.props.children foo={2}}
</div>

}
});

var App = React.createClass({
render: function () {
return (
<Wrapper>
{this.props.foo}
</Wrapper>
)
}
});


jsfiddle

Answer

Imagine Javascript code

this.props.children foo=2

this is what your expression is transpiled into from JSX into plain JS. The fact is, you can't pass props to children directly because children isn't a React component. To make it work, you need to map through children and pass your props per every item of iterable.

The problem that comes next is that you can't simply do

this.props.children.map(child => (
  <Child foo={2} />
))

because, first, you'll receive TypeError because map is undefined, and second, you'd lose all initial props of every child.

You'll need to use React.Children.map static function as well as React.cloneElement to make it work:

React.Children.map(children, child => React.cloneElement(child, {
  foo: 2
}))

This way, every child element preserves its own props passed from parent element and, in addition to them, receive new props you define. Be careful with it because you may unintentionally redefine values of some props, too.


Your example code will then look like

var Wrapper = React.createClass({
    render: function () {
        const {
            foo
        } = this.props;

        return (
            <div>
                {React.Children.map(this.props.children, child => React.cloneElement(child, {
                    foo
                }))}
            </div>
        );
    }
});

var App = React.createClass({
    render: function () {
        return (
            <Wrapper foo={2}>
                <div>I should be a component</div>
                <div>I should be a component, too</div>
                <div>We all should be components</div>
            </Wrapper>
        );
    }
});
Comments