Register to get access to free programming courses with interactive exercises

Children JS: React

UI elements have a hierarchical structure. For example, it is the card in Bootstrap:

<div class="card">
  <img class="card-img-top" src="..." alt="Card image cap">
  <div class="card-body">
    <h4 class="card-title">Card title</h4>
    <p class="card-text">
      Some quick example text to build on the card title and make up the card's content
    </p>
    <a href="#" class="btn btn-primary">Go somewhere</a>
  </div>
</div>

HTML conforms to the nature of UI and naturally allows you to create compositions of elements by nesting tags within each other.

JSX works the same way. So far, we have talked about this feature for embedded components. Now it's time to learn how to repeat this behavior in self-written ones.

Here you can see the example, based on the <Alert /> component from Bootstrap:

See the Pen YxgWVm by Hexlet (@hexlet) on CodePen.

In the example above, only the main div is mandatory. The content depends on the specific situation. It's substituted using the children property.

See the Pen js_react_children_alert_component by Hexlet (@hexlet) on CodePen.

Note that we use the component as a paired tag in JSX:

const vdom = (
  <Alert>
    <p>Don't forget to use margin utilities to keep things nice and tidy</p>
  </Alert>
);

Everything between the opening and closing tags goes inside the children prop.

But beware that the children property data type depends on the content. For example, the property will be undefined when we use the tag as a single <div />.

If this content is a string, it'll be inside children. After some processing, anyway. JSX removes whitespace from the beginning and end of a string, including blank lines. The following examples will be displayed in the same way:

<div>Hello World</div>

<div>
  Hello World
</div>

<div>
  Hello
  World
</div>

<div>

  Hello World
</div>

Any single child component will also be represented in children. In all other cases, children will contain an array.

If you look closely at the React documentation, you'll see the definition of children as an opaque data structure. In other words, we can convey anything on the outside, so we can't unequivocally rely on the type of this prop.

This kind of behavior can lead to hard-to-find mistakes. For example, checking this.props.children.length doesn't always give the number of children. If children children is a single element, such as a string, then the length property will return the length of that string:

class MyComponent extends React.Component {
  render() {
    const { children } = this.props
    return <p>Count: {children.length}</p>
  }
}

// <p>Count: 4</p>
<MyComponent>Text</MyComponent>

It is why React offers functions specifically designed to manipulate the children prop, which we can access through React.Children. These functions are well-equipped to handle the intricacies of children. They automatically verify its type and perform appropriate checks based on the data type.

React.Children.map()

In the lesson on processing collections, you learned that when working with a list in React, we should assign a key prop to each item. If using React.Children.map, React won't throw a warning if you fail to do so. This omission is intentional, as descendants often lack unique identifiers.

React.Children.count()

class ChildrenCounter extends React.Component {
  render() {
    const { children } = this.props
    return <p>Count: {React.Children.count(children)}</p>
  }
}

// Count: 1
<ChildrenCounter>
  Second!
</ChildrenCounter>

// Count: 2
<ChildrenCounter>
  <p>First</p>
  <ChildComponent />
</ChildrenCounter>

// Count: 2
<ChildrenCounter>
  {() => <h1>First!</h1>} // will be skipped because it's not a dom-element
  Second!
  <p>Third!</p>
</ChildrenCounter>

In addition to the above, you may need to handle child elements before output by changing a part in their props. Of course, we can't do it directly because props are immutable. You can achieve this behavior by cloning elements with React.cloneElement().


Are there any more questions? Ask them in the Discussion section.

The Hexlet support team or other students will answer you.

About Hexlet learning process

For full access to the course you need a professional subscription.

A professional subscription will give you full access to all Hexlet courses, projects and lifetime access to the theory of lessons learned. You can cancel your subscription at any time.

Get access
130
courses
1000
exercises
2000+
hours of theory
3200
tests

Sign up

Programming courses for beginners and experienced developers. Start training for free

  • 130 courses, 2000+ hours of theory
  • 1000 practical tasks in a browser
  • 360 000 students
By sending this form, you agree to our Personal Policy and Service Conditions

Our graduates work in companies:

<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.bookmate">Bookmate</span>
<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.healthsamurai">Healthsamurai</span>
<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.dualboot">Dualboot</span>
<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.abbyy">Abbyy</span>
Suggested learning programs
profession
Development of front-end components for web applications
10 months
from scratch
Start at any time

Use Hexlet to the fullest extent!

  • Ask questions about the lesson
  • Test your knowledge in quizzes
  • Practice in your browser
  • Track your progress

Sign up or sign in

By sending this form, you agree to our Personal Policy and Service Conditions
Toto Image

Ask questions if you want to discuss a theory or an exercise. Hexlet Support Team and experienced community members can help find answers and solve a problem.