DEV Community

Cover image for React children 👶 💭 – why, when, how
Franca
Franca

Posted on

React children 👶 💭 – why, when, how

Use Case

React is great for building reusable components. Components often come in multiple variations – most of the time we can pass props to the component and all good.

<Button color="red" text="Click me!" />
Enter fullscreen mode Exit fullscreen mode

However, what if we build a component that doesn’t only change in style but also contains different JSX? This is often the case with complex, nested components like accordions, carousels and tabs or buttons with text and icon.

To keep it simple, imagine a <Post /> component for a blog post. All posts look alike but vary in content.

The Post.js component within App.js

The plain Post component could look like this:

// Post.js
export const Post = () => {
  return (
    <section>
      <div>...Post content here...</div>
    </section>
  );
};
Enter fullscreen mode Exit fullscreen mode

To use Post in App.js , it's possible to create a property, e.g. content that contains all kind of JSX like this:

// App.js
<Post content={
  <>
    <h1>My first Post</h1>
    <p>Some intro text</p>
    <p>A paragaph</p>
  </>
}/>
Enter fullscreen mode Exit fullscreen mode

Note: the empty <> tag is a Fragment.

See the CodeSandbox example here.

It’s just that this solution doesn’t look simple and clean. It’s not that we want to pass certain properties to the component, it’s more that we want to define what’s inside. In this case, use React children!

React Children In Action 👶

You don’t pass children like a property, you place it inside the component tags as if you'd write plain old HTML.

// App.js
<Post>
  <h1>My first Post</h1>
  <p>Some intro text</p>
  <p>A paragaph</p>
</Post>
Enter fullscreen mode Exit fullscreen mode

This looks so much better! It feels like writing HTML with superpowers!

You created your own component <Post> and filled it with JSX tags. You can insert custom React components as well!

The Post component consists of various different elements.

But – we have to tweak the component itself a little. At the moment, the Post component looks like this:

// Post.js
export const Post = () => { ... }
Enter fullscreen mode Exit fullscreen mode

As children are special properties, you don’t have to declare them when using the component, but you have to tell the component itself that children are welcome. The word children is a special word in the React world with a set meaning like function or const.

// Post.js
export const Post = ({children}) => { ... } 
Enter fullscreen mode Exit fullscreen mode

In the next step, you have to define the children's location inside the component’s JSX structure:

// Post.js
export const Post = ({ children }) => {
  return (
    <section>
      ...
      <div>{children}</div>
      ...
    </section>
  );
};
Enter fullscreen mode Exit fullscreen mode

Post.js contains fixed JSX tags as well as a space for flexible children.

See the CodeSandbox example here

⚠️ Caution

Only use children if you can’t control the component’s content. If you know that a component is always going to be based on the same JSX structure, it’s better to pass string props for the heading, etc. Be as strict as possible.

Also, don’t try to style the children. Don’t do this:

// App.js
<Post>
  <h1 className="post__heading">My first Post</h1>
  <p>Some intro text</p>
  <p>A paragaph</p>
</Post>
Enter fullscreen mode Exit fullscreen mode

You don’t have a place to define that CSS class.

There are several options in this case:

1. Create Smaller Components

If the heading is used universally, you could create a Heading component:

// App.js
<Post>
  <Heading>My first Post</Heading>
  <p>Some intro text</p>
  <p>A paragaph</p>
</Post>
Enter fullscreen mode Exit fullscreen mode

2. Use Props Instead

If you want to use a special post__heading class, the Post component itself is the right place to do this. Just pass the heading as a normal prop.

// App.js
<Post heading="My first Post"> // Property
  <p>Some intro text</p> // Children
  <p>A paragaph</p> 
</Post>
Enter fullscreen mode Exit fullscreen mode
// Post.js
export const Post = ({ heading, children }) => {
  return (
    <section>
      <div className="post">
        <h1 className="post__heading">{heading}</h1>
        {children}
      </div>
      <a>See all posts</a>
    </section>
  );
};
Enter fullscreen mode Exit fullscreen mode

3. Split Component Into Smaller Functions

This is my advice if you want to style the children specifically and use more than one JSX tag.

// App.js
<Post heading="My first Post">
  <p>Some intro text</p>
  <p>A paragaph</p>
</Post>
Enter fullscreen mode Exit fullscreen mode
// Post.js
const PostMain = ({ content }) => {
  return <div className="post__main">{content}</div>;
};

export const Post = ({ heading, children }) => {
  return (
    <section>
      <div className="post">
        <h1 className="post__heading">{heading}</h1>
        <PostMain content={children} />
      </div>
      <a>See all posts</a>
    </section>
  );
};
Enter fullscreen mode Exit fullscreen mode

See it in action in this CodeSandbox

Advanced Case: Split Up Your Children

We can go even further and split our Post components into intro, main and outro 😎

// App.js
<Post heading="My first Post">
    <PostIntro>
      <p>Some intro text</p>
      <p>Intro paragaph</p>
    </PostIntro>
    <PostMain>
      ...
    </PostMain>
    <PostOutro>
      ...
    </PostOutro>
</Post>
Enter fullscreen mode Exit fullscreen mode

PostIntro, PostMain and PostOutro are small, separate components that can be used as children inside the Post component.

// Post.js
export const PostIntro = ({ children }) => {
  return <div className="post__intro">{children}</div>;
};

export const PostMain = ({ children }) => {
  return <div className="post__main">{children}</div>;
};

export const PostOutro = ({ children }) => {
  return (
    <div className="post__outro">
      {children}
      <a>See all posts</a>
    </div>
  );
};

export const Post = ({ heading, children }) => {
  return (
    <section>
      <div className="post">
        <h1 className="post__heading">{heading}</h1>
        {children}
      </div>
    </section>
  );
};
Enter fullscreen mode Exit fullscreen mode

The Post component itself is "stupid" and doesn't know which children will be passed. This is a simple example, but if your components contain a lot of logic and/or JSX, this is a way to separate concerns.

Final relationship between App.js and Post.js

See the finished example here – feel free to fork and play with it!


Linklist

Top comments (1)

Collapse
 
lesleyvdp profile image
Lesley van der Pol

PostIntro, PostMain and PostOutro are small, separate components that can be used as children inside the Post component.

The way you set this up is why I'm such a big fan of using styled components within React, it makes this very seemless! :)