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 useprops.children
const Picture = (props) => {
return (
<div>
<img src={props.src}/>
{props.children}
</div>
)
}
This component contains an
<img>
that is receiving someprops
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
How to Stop Babel from Transpiling 'This' to 'Undefined' (And Inserting "Use Strict")
How to Test If a String Is JSON or Not
How to Calculate the Latlng of a Point a Certain Distance Away from Another
How to Remove a Key from a JavaScript Object
What Is Difference Between Axios and Fetch
How to Rotate a 3D Object on Axis Three.Js
Remove All Special Characters Except Space from a String Using JavaScript
How to Determine If an Image Has Loaded, Using JavaScript/Jquery
Getting Binary Content in Node.Js Using Request
JavaScript Audio Play on Click
JavaScript Settimeout() Won't Wait to Execute
Fastest Way to Check a String Contain Another Substring in JavaScript
How to Trigger Ngclick Programmatically
How to Add a Key Prop to a React Fragment
Require Is Not Defined? Node.Js