Children of the Reactolution
When I first came across this.props.children I couldn't fathom a use for it. I (un)ashamedly used it cargo-style when setting up ReactRouter - the router has children that are rendered dynamically based on the route. Sure, that made sense but when else could I use that? Why would a component have children that weren't DOM nodes?
One of the most important approaches to take when using React is to abandon the old way of thinking - React is as much about methodologies as it is about utilities. Once you realise this things start making a lot more sense. My discovery of the this.props.children magic seemed to manifest suddenly; after a Five Guys lunch and some table-tennis.
Usage
Once you do discover its magic (and forget how you used to do things), you start seeing where this.props.children can be useful.
Using Redux and the Smart/Dumb Components pattern I ran into problems when trying to nest dumb components. State updates on the child dumb component would trigger a re-render on the parent as data was flowing from the smart component through the dumb parent and into the dumb child. Not good.
Then this lightbulb flashed on:
<Parent><Child /></Parent>An example
Let's look at a <Loader /> component as an example of this practice. The component takes the content that is being loaded as its children:
import React, { Component } from 'react';
import Loader from '../component/loader';
import SomeComponent from '../component/somecomponent';
class Container extends Component {
render() {
const { isFetching } = this.props;
return (
<div>
<Loader loading={isFetching}>
<SomeComponent />
</Loader>
</div>
);
}
}The loader's children aren't rendered until the load process has completed:
import React, { Component, PropTypes } from 'react';
export default class Loader extends Component {
render() {
const { loading, children } = this.props;
const spinner = <div className='spinner'></div>;
const content = loading ? spinner : children;
return (
<div>
{content}
</div>
);
}
}
Loader.propTypes = {
loading: PropTypes.bool.isRequired
};Props to Children
It is also possible to pass props to children through cloning:
import React, { Component, Children, cloneElement } from 'react';
export default class Nav extends Component {
render() {
const { children } = this.props;
let clones = Children.map(children, child => {
return cloneElement(child, {className: 'something dynamic', activeClassName: 'active'});
});
return (
<div>
{clones}
</div>
);
}
}Interesting stuff. And, one last time - this.props.children.