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.