Understand the concepts of ownership and children in ReactJS

February 10, 2015



Let’s explore how does the ownership works in React. What exactly is a child in React’s world by looking at the special property : this.props.children.

Summary

Luke, I’m your.. owner?

When we do:

var MyContainer = React.createClass({
  render: function() {
    return <MyChild value={this.props.value} />
  }
});
// Or in ES6
const MyContainer = (props) => <MyChild value={props.value} />
  • <MyContainer> is the owner of <MyChild>
  • <MyChild> is the ownee of <MyContainer>

We don’t talk about parent/child, which refers to the DOM relationships.

If we wrap a <div> around <MyChild>:

var MyContainer = React.createClass({
  render: function() {
    return <div><MyChild value={this.props.value} /></div>
  }
});
// Or in ES6
const MyContainer = (props) => <div><MyChild value={props.value} /></div>

<MyContainer> is not the parent of <MyChild> (the <div> is in between), but it’s more generally its owner.

In the DOM hierarchy, the <div> is the representation of <MyContainer> which is the parent of whatever <MyChild> can represent.

You can see it through the React Chrome Developer Tools:

devtools

  • <MyContainer> does not have any owner
  • The owner of <MyChild> is <MyContainer>, not the <div> in-between (the owner of the <div> is also <MyContainer>).
  • The owner of the <span> is <MyChild>

To resume:

  • an owner is a React Element
  • an ownee can be anything (a React element or a pure HTML tag).

To find the owner of a node, we need to look for its closest React element through its ancestors hierarchy. It’s the one that render() it (and sets its props if any).

There are many types of children

Let’s focus on the special property this.props.children.

This is a property automatically set by React on our components that contains the children of the current component.

Don’t use children as a name for your own props, you might have troubles (ie: it will be override if you really have children in your component).

Here is a simple component that includes its children into a <div>.

var Parent = React.createClass({
  render: function () {
    return <div>{this.props.children}</div>;
  }
});
React.render(<Parent>
              <span className="child">whining</span>
             </Parent>, document.getElementById('container'));

That renders:

<div id="container">
  <div data-reactid=".0">
    <span class="child" data-reactid=".0.0">whining</span>
  </div>
</div>

this.props.children corresponds to the content put inside the <Parent></Parent> where it was rendered. In this example, this.props.children is a single ReactElement (type span).

But this.props.children can also be an array of two ReactElement of type span:

React.render(<Parent>
              <span className="child">whining</span>
              <span className="child">whining more</span>
            </Parent>, document.getElementById('container'));

More generally, this.props.children can contains:

  • undefined:

    • <Component />
    • <Component></Component>
  • a single ReactElement:

    • <Component><span></span></Component>
    • <Component><ChildComponent></ChildComponent><Component>
  • an array of ReactElements :

    • <Component> <span></span> <ChildComponent></ChildComponent> </Component>
  • a string:

    • <Component>i'm a nice string</Component>

Because of all the types, it can be complicated to work with this property without bloating the code.

React Children helpers

Hopefully, the React team had created some helpers to do the dirty job and make our code cleaner:

  • React.Children.map : iterate through them calling your function, and returns an array (or undefined if no child) as result
  • React.Children.forEach : iterate through them calling your function
  • React.Children.count : number >= 0
  • React.Children.only : if you don’t have one child exactly, it throws the error Uncaught Error: Invariant Violation: onlyChild must be passed a children with exactly one child (even if I have a string a child which I think is a bug, because .count returns 1), otherwise returns it

Here is a small example that renders only children of type span or MyComponent:

var ShowOnlySpansOrMyComponent = React.createClass({
  render: function() {
    var filtered = React.Children.map(this.props.children, function(child) {
      if (child.type === 'span' || child.type === MyComponent) {
        return child;
      }
    });
    return <div>{ filtered }</div>;
  }
});

React.render(<ShowOnlySpansOrMyComponent>
              you have to <span>work</span>
              <div>AB</div>
              <MyComponent />
              <span>now</span>
             </ShowOnlySpansOrMyComponent>, document.getElementById('container'));

Here is the list of the children with their type:

- " you have to " : undefined
- ReactElement : span
- ReactElement : div
- ReactElement : function (props, context, updater) // MyComponent's (ReactClassComponent's) function
- ReactElement : span

In older versions, each newline in JSX were creating a string child " ". And we had to use MyComponent.type instead of just MyComponent reference.

Only the <span> and <MyComponent> appear in the rendering.

work
my component
now

Feel free to share this article: 

Join the club and receive an email when I post a new article! No spam ever, no worries.

Me, Stéphane Derosiaux

Hi, I'm Stéphane, CTO of Conduktor, a major Apache Kafka Platform. I live in France. Enthousiast and eager to learn, I'm always seeking for challenges. Find out more about me.



Ready to work with me?

Tell me everything!
© Copyright 2018-2022 · Stéphane Derosiaux · All Rights Reserved.