What Is {This.Props.Children} and When You Should Use It

What is {this.props.children} and when you should use it?

What even is ‘children’?

The React docs say that you can use props.children on components that represent ‘generic boxes’ and that don’t know their children ahead of time. For me, that didn’t really clear things up. I’m sure for some, that definition makes perfect sense but it didn’t for me.

My simple explanation of what this.props.children does is that it is used to display whatever you include between the opening and closing tags when invoking a component.

A simple example:

Here’s an example of a stateless function that is used to create a component. Again, since this is a function, there is no this keyword so just use props.children

const Picture = (props) => {
return (
<div>
<img src={props.src}/>
{props.children}
</div>
)
}

This component contains an <img> that is receiving some props and then it is displaying {props.children}.

Whenever this component is invoked {props.children} will also be displayed and this is just a reference to what is between the opening and closing tags of the component.

//App.js
render () {
return (
<div className='container'>
<Picture key={picture.id} src={picture.src}>
//what is placed here is passed as props.children
</Picture>
</div>
)
}

Instead of invoking the component with a self-closing tag <Picture /> if you invoke it will full opening and closing tags <Picture> </Picture> you can then place more code between it.

This de-couples the <Picture> component from its content and makes it more reusable.

Reference: A quick intro to React’s props.children

ReactJS: Why use this.props.children?

In my applications I rarely use this.props.children, because I often know specifically what children I want to render. In libraries, or components written to be re-used outside of a specific component hierarchy, I've seen it often. I think this.props.children has more relevance to that use-case.

Edit: I thought I'd elaborate on some cases that this.props.children can come in handy. One such example is when creating components which follow the 'render prop' pattern. i.e. I've got some components that require pulling data in from multiple 'render prop' HoC's, such as an Apollo Query component as well as a state management HoC. I combined all my different data sources into one HoC and then called children as a function, passing in the result of pulling out all the data I needed. That being said these days I prefer and look forward to wider adoption of Hooks as an alternative to render props.

Really any component which you want to render arbitrary children; another example I've used props.children is when creating a HoC that required a user be authenticated before rendering the child, redirecting to a login screen when the user isn't logged in. I could wrap any of my 'protected' screen components with this auth HoC.

It's still something the majority of my components don't use, but just another tool to be applied when the situation warrants.

React props vs children. What to use when?

children prop is something that you use when the structure of what needs to be rendered within the child component is not fixed and is controlled by the component which renders it.

However if behaviour of the component is consistent across all its renders it can define the specific props that it needs and the parent can pass them to it.

A very simple example could be a Navbar which can use children. For a Navbar the items that it needs to render as well as the order or alignment or items depends on how it needs to be used at different instances or across different pages. For instance Navbar somewhere can have Search component at one place and at some other place not have it. Also the menus may sometimes be needed to the left followed by Login menu item to the right and a searchbar between them and sometimes they may all be present to the right without the searchbar. In such cases the parent component can control how the internal structure would be

What is props.children?

props.children is a prop like every other prop in React, but it's passed differently (when using JSX) between tags:

<Component>text</Component>

What you put between the tags will be passed to component as props.children. It can be:

undefined, null, a boolean, a number, a string, a
React element, or an array of any of those types recursively.

It can also be a function that returns one of the above ^ to create render prop pattern.

If you want to directly work on children prop (filter or map them), you will probably need some React utility functions.

That's pretty much it. There are of course more details in React documentation.

How props.children works on a React component?

props.children means that React will render whatever u put between Layout component.

For ex, if u put a div block between Layout components, props.children will be that div.

Why use this.props.children?

I like to think of components that make use of props.children as general wrappers, like most other HTML elements.

Think about the fieldset element.

<form action="/post">
<input type="text" name="myValue" placeholder="Some Data" />
<input type="submit" value="Submit!" />
</form>

What a pretty form we have made! But I want it to look...different. I want it to kind of look more visually like a form. Like I want some borders around it, maybe a little label in the top to describe it...Ahh I'll wrap it in a fieldset!

<fieldset>
<legend>A Pretty Form</legend>
<form action="/post">
<input type="text" name="myValue" placeholder="Some Data" />
<input type="submit" value="Submit!" />
</form>
</fieldset>

Now it looks just how I want! Sprinkled in a little legend too, to make this example...legendary.

The point is though, fieldset provides a reusable component with certain attributes that can be used to group HTML content. It's child elements are absolutely irrelevant to it's functionality.

Could we use the same principle in React? Yes. And it can be much more powerful!

Let's say we want to have a special ReactFieldset component, based on an HTML fieldset, that has it's own functionality. I'm not going to code that all out, because who has the time? But imagine you made a ReactFieldset component with a bunch of it's own functionality: it can collapse, it can move, it can do all kinds of things! And it can also hold any kind of content.

Well, then all you need to do in it's render function is:

render() {
return <fieldset { ...superFunctionalityControllingProps }>
{ this.props.children }
</fieldset>
}

Tada! You now have a reusable component that has it's own functionality, and can hold any children.

So the point is: this.props.children can be used when the children aren't really that important at all! The emphasis can actually just be on the component itself, whereas the children are arbitrary components it just happens to house. They needn't even be functionality related at all.

This is used a lot in React Native. Many different components have their own functionality, but can house any children, because they are just "wrapper" building blocks.

How to pass props to {this.props.children}

Cloning children with new props

You can use React.Children to iterate over the children, and then clone each element with new props (shallow merged) using React.cloneElement.

See the code comment why I don't recommend this approach.

const Child = ({ childName, sayHello }) => (
<button onClick={() => sayHello(childName)}>{childName}</button>
);

function Parent({ children }) {
// We pass this `sayHello` function into the child elements.
function sayHello(childName) {
console.log(`Hello from ${childName} the child`);
}

const childrenWithProps = React.Children.map(children, child => {
// Checking isValidElement is the safe way and avoids a
// typescript error too.
if (React.isValidElement(child)) {
return React.cloneElement(child, { sayHello });
}
return child;
});

return <div>{childrenWithProps}</div>
}

function App() {
// This approach is less type-safe and Typescript friendly since it
// looks like you're trying to render `Child` without `sayHello`.
// It's also confusing to readers of this code.
return (
<Parent>
<Child childName="Billy" />
<Child childName="Bob" />
</Parent>
);
}

ReactDOM.render(<App />, document.getElementById("container"));
<script src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
<div id="container"></div>


Related Topics



Leave a reply



Submit