Ownership and children in ReactJS

February 10th, 2015 | javascript, react |

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

Luke, I’m your.. owner?

When you do:

var MyContainer = React.createClass({
    render: function() {
        return 
    }
});

is the owner of , and is the ownee.

We don’t talk about parent/child, this is used to talk about the DOM only.

In this example:

var MyContainer = React.createClass({
    render: function() {
        return 
} });

is not the parent of , it’s only its owner.

Being the parent refers to the DOM hierarchy, thus in this case, it’s the

that is the child of and the parent of . But let’s focus on the ownership.

You can see it through the React Chrome Developer Tools for instance:


We can see that :

  • does not have any owner
  • The owner of is , not the
    in-between (the owner of the
    is too).
  • The owner of the deep is

To resume, an owner can only be a React Component, an ownee can be anything (component or basic html tag). To find the owner of a node, you need to look for its closest React Component through its ancestors hierarchy, it’s the one that render() it (and sets its props if any).

this.props.children in-depth

Now, let’s focus about the children, and especially the special property this.props.children.

This is a property automatically set by React on your component that contains the children of the current component you are. 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

.

var Parent = React.createClass({
  render: function () {
      return 
{this.props.children}
; } }); React.render(whining, document.getElementById('container'));

That renders:

whining

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

In this example, this.props.children is an Array of two ReactElement of type span :

React.render(
                 whining
                 whining more
             ,
             document.getElementById('container'));

Often we can find self-closed tag when rendering components, for instance return , but this is just the case where this.props.children === undefined (it’s the same if you do ).
 


Meaning that this.props.children can contains either :

  • undefined : or

  • a single object ReactElement: or

  • an array of ReactElement :

  • a string : i'm a nice string


So, basically, 4 different types. You’re going to have some bloat code to handle all those cases. Or not. Hopefully, the React team had created some helpers to do the dirty job and make our code cleaner (Note: by default it’s not always an array to avoid useless allocation):

  • 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, I think it’s 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 onlySpans = React.Children.map(this.props.children, function(child) {
            if (child.type === 'span' || child.type === MyComponent.type) {
                return child;
            }
        });
        return 
{ onlySpans }
; } }); React.render( you have to work
AB
now
, document.getElementById('container'));

Here is the list of the children :

" you have to " : no type
ReactElement : span
" " : no type
ReactElement : div
" " : no type
ReactElement : here, type is function (props) : this is the ReactElement constructor..
" " : no type
ReactElement : span
" " : no type

Only the and appear in the rendering.
To compare the type of components, notice that we used the value of MyComponent.type which is the same constructor of ReactElement we are talking about.

Published by

ctheu

Hey. I love computer sciences almost since I'm born. I work with frontend and backend technologies; I can't make my mind ! Let's share some tips about how some of them work, shall we ?