Passing JSX as children
Nest content inside your own components with the children prop, and build reusable wrappers like cards and layouts.
With HTML you nest tags all the time: a <p> inside a <div>, a <li> inside a <ul>. The outer tag doesn't need to know what is inside it. It only provides the box.
You'll often want your own components to work the same way. Think of a card with a border and a shadow, where the content changes every time. In this lesson you'll learn how a component can wrap content that the parent decides on.
Nesting content inside your own component
Look at how Card is used below. Instead of a self-closing <Card />, it has an opening and a closing tag, with other JSX in between:
When you put JSX between a component's tags, React passes it to that component as a prop called children. You read it like any other prop, by destructuring, and you place {children} wherever the content should appear.
Card doesn't know or care whether it holds a book title, a message or a whole form. It only knows how to draw the box. That makes it reusable in many places.
What can children be?
children is whatever you put between the tags. That can be:
- plain text, such as
<Card>Hello</Card>; - one element, such as
<Card><h2>Hi</h2></Card>; - several elements side by side;
- other components, such as
<Card><BookCard book={dune} /></Card>; - nothing at all, in which case
childrenisundefinedand nothing is rendered.
A wrapper component can also take normal props alongside children. Here Panel takes a title prop for its heading, and children for its body:
Try adding a third Panel called "Finished" with a book of your own inside it.
Card is written as function Card({ children }) and returns a div with children inside it. What appears when you render a Card with an h2 and a p between its tags?
Passing JSX through other props
children is the natural place for the main content. Sometimes a wrapper has more than one hole to fill, such as a page with a header, a sidebar and a main area. Because JSX is a value like any other, you can pass it through any prop you like, not only children:
Props that take JSX like header and sidebar are often called slots. They are ordinary props. The only difference is that their value happens to be JSX. Use children for the main content, and named slots when you need more than one place to put things.
Deep diveCan a component inspect or change its children?
React has a Children helper that can count or loop over children, but you will rarely need it. In modern React code, it is better to treat children as a sealed package. The wrapper decides where to put it and leaves the contents alone.
If a component needs to know details about the items inside it, pass them as data instead, for example items={books}, and let the component render them itself. You'll do exactly that with BookList in the Rendering lists lesson.
Build a Shelf wrapper
Create a Shelf component that takes a title prop and children. It should render a section with the class shelf, an h2 with the title, and then the children. Use it in App to put the two book cards on a shelf called "Favorites".
Show solution
Shelf destructures both title and children, and App wraps the cards in <Shelf title="Favorites">.
Notice that Shelf has no idea it holds book cards. You could reuse it for anything else that needs a titled, bordered box.
A page needs a header area and a main content area, both filled in by the parent. Which design fits best?
Day 2 progress