Note: You need to use import * as React from 'react' here instead of import React from 'react' to get access to the React.Node type. We explain why that is in the React Type Reference.

However, if you want to do anything more powerful with the React children API then you will need a strong intuition of how React handles children. Let us look at a couple of cases before continuing to help build that intuition.

<MyComponent />;
// which is the same as...
React.createElement(MyComponent, {});

If you pass in no children when creating an element of MyComponent then props.children will not be set. If you try to access props.children, it will be undefined.

What happens when you have a single child?

<MyComponent>{42}</MyComponent>;
// which is the same as...
React.createElement(MyComponent, {}, 42);

If you pass in a single value then props.children will be exactly that single value. Here props.children will be the number 42. Importantly, props.children will not be an array! It will be exactly the number 42.

What happens when you have multiple children?

<MyComponent>{1}{2}</MyComponent>;
// which is the same as...
React.createElement(MyComponent, {}, 1, 2);

Now, if you pass two values then props.children will be an array. Specifically in this case props.children will be [1, 2].

Multiple children may also look like:

<MyComponent>{'hello'} world</MyComponent>;
// which is the same as...
React.createElement(MyComponent, {}, 'hello', ' world');

In which props.children would be the array ['hello', ' ', <strong>world</strong>].

Moving on to the next case. What happens if we have a single child, but that child is an array?

<MyComponent>{[1, 2]}</MyComponent>;
// which is the same as...
React.createElement(MyComponent, {}, [1, 2]);

This follows the same rule that when you pass in a single child then props.children will be exactly that value. Even though [1, 2] is an array it is a single value and so props.children will be exactly that value. That is to say props.children will be the array [1, 2] and not an array of arrays.

Here props.children will be an array of arrays. Specifically props.children will be [[1, 2], [3, 4]].

The rule to remember with React children is that if you have no children then props.children will not be set, if you have one single child then props.children will be set to exactly that value, and if you have two or more children then props.children will be a new array of those values.

Note: Watch out for whitespace! Take the following:

<MyComponent>{42} </MyComponent>

This compiles to: React.createElement(MyComponent, {}, 42, ' '). (With the spaces!) See how the spaces show up as part of the children? In this case props.children would be [42, ' '] and not the number 42. However, the following is fine:

<MyComponent>
{42}
</MyComponent>

It will compile to what you would expect: React.createElement(MyComponent, {}, 42).

Newlines and indentation after newlines are stripped, but watch out for whitespace when using a component with strict types around what children may be.

Note: Watch out for comments! Take the following:

<MyComponent>
// some comment...
{42}
</MyComponent>

This compiles to: React.createElement(MyComponent, {}, '// some comment...', 42). See how the comment is included in the element’s children? In this case props.children would be ['// some comment...', 42] which includes the comment. To write comments in JSX use the following syntax:

<MyComponent>
{/* some comment... */}
{42}
</MyComponent>

Now let's see how you would take this intuition and type the children of various React components.

Only allowing a specific element type as children.

Sometimes you only want a specific component as the children to your React component. This often happens when are building a table component which needs specific column children components, or a tab bar which needs specific configuration for each tab. One such tab bar component that uses this pattern is React Native’s <TabBarIOS> component.

React Native’s <TabBarIOS> component only allows React element children and those elements must have a component type of <TabBarIOS.Item>. You are expected to use <TabBarIOS> like:

Enforcing that a component only gets a single child.

Sometimes you want to enforce that your component will only receive a single child. You could use React.Children.only() function to enforce this constraint, but you could also enforce this in Flow. To do this you would not wrap the type for your children in React.ChildrenArray<T>. Like so:

The type for children is a function that takes in some object type and returns a React.Node which is the type for any value that can be rendered by React. A children function does not need to return React.Node. It could return any type, but in this case react-router wants to render the result returned by the children function.

This pattern is also not limited to function children. You could also pass in arbitrary object or class types.

The React Native <View> component will allow any primitive value or any React element as its children. However, <View> does not allow strings or numbers as children! You could use React.Node as the children type for <View>, however React.Node includes strings which we don’t want for <View>. So we need to create our own type.