Understanding the React.Children api with common use cases
Published: 2021-06-19 00:32:29

We all might have used *{this.props.children}*  inside the React Components to get hold of the child elements. 
The *{this.props.children}* is what can be called as an opaque data structure. There are very limited operations or manipulations that we can perform on this. That is where the **React.Children** api comes into picture. 

React provides us with a **Children** api that helps in dealing with this opaque data structure. 

Let's take a look at the use cases using an example - 

ParentElement.js
```javascript
import { Component } from "react";

class ParentElement extends Component {
  render() {
    // Inside the Parent component we are directly displaying the props.children
    return <div>{this.props.children}</div>;
  }
}

export default ParentElement;
``` 
ChildElement.js
```javascript
import { Component } from "react";
import Parent from "./ParentElement";

// This is a simple example for using the Parent component
// And accessing the child elements wrapped inside the Parent
class ChildElement extends Component {
  render() {
    return (
      <Parent>
        <div>Child 1</div>
        <div>Child 2</div>
        <div>Child 3</div>
        <div>Child 4</div>
      </Parent>
    );
  }
}

export default ChildElement;
``` 
Output to the following code

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1624058488344/rMSg_BWVG.png)

Now let us look at the scenarios that we might encounter. 

## 1. React.Children.toArray()

#### Scenario 1 - We need to display only the first Child inside the ParentElement even though we are getting 4 div's as immediate child elements from {this.props.children}

The data that we get from *{this.props.children}* is called opaque data. This is treated as a single entity and we cannot distribute this in the form of an array. In order to convert this to an array, we can use the **toArray** method from the React.Children api

This method takes in the this.props.children as argument and converts it to an array with each immediate child forming the elements of the array. 

Let us take a look at this implementation and try to solve the issue mentioned in scenario 1. 

ParentElement.js
```javascript
import React, { Component } from "react";

class ParentElement extends Component {
  render() {
    const { children } = this.props;
    // toArray method is called to convert this.props.children to an array
    // We are then referencing the first element using index 0
    return <div>{React.Children.toArray(children)[0]}</div>;
  }
}

export default ParentElement;
```
Output after implementing the toArray method

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1624059251167/b6UTWMFcs.png)


## 2. React.Children.count()

#### Scenario 2 - We need to get the count of the immediate child elements. 

Again, this is impossible to calculate on this.props.children as it is considered as a single entity. 

React.Children gives us the **count** method to do this. 

It takes in this .props.children as argument and returns the count of the immediate child elements. 

ParentElement.js
```javascript
import React, { Component } from "react";

class ParentElement extends Component {
  render() {
    const { children } = this.props;
    // count method is used to count the immediate child elements in this.props.children
    // Even though the count is 4, we are only displaying Child 1
    return (
      <div>
        <p>
          Total Count of Children: {React.Children.count(this.props.children)}
        </p>
        {React.Children.toArray(children)[0]}
      </div>
    );
  }
}

export default ParentElement;

``` 

## 3. React.Children.only()

#### Scenario - 3 - We need to make sure that the this.props.children is such that it only has 1 element as its immediate child. This one element in turn can have multiple child elements inside it. But on the highest level we need to ensure that there is only one element. 

We can use the **only** method from React.Children api for this.

Let us look at the code below - 

ChildElement.js
```javascript
import { Component } from "react";
import Parent from "./ParentElement";

// This is a simple example for using the Parent component
// And accessing the child elements wrapped inside the Parent
class ChildElement extends Component {
  render() {
    return (
    // There are 4 immediate child elements here
      <Parent>
        <div>Child 1</div>
        <div>Child 2</div>
        <div>Child 3</div>
        <div>Child 4</div>
      </Parent>
    );
  }
}

export default ChildElement;

``` 
ParentElement.js
```javascript
import React, { Component } from "react";

class ParentElement extends Component {
  render() {
    const { children } = this.props;
    // count method is used to count the immediate child elements in this.props.children
    // Even though the count is 4, we are only displaying Child 1
    return (
      <div>
        <p>
          Total Count of Children: {React.Children.count(this.props.children)}
        </p>
        {/* Making use of the only method */}
        {React.Children.only(children)}
      </div>
    );
  }
}

export default ParentElement;

``` 
Output when there are 4 child elements 

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1624060122212/egEwy1X9W.png)

Now, in order to comply with the **only** method, we will wrap the 4 Child elements in a single div

ChildElement.js
```javascript

import { Component } from "react";
import Parent from "./ParentElement";

// This is a simple example for using the Parent component
// And accessing the child elements wrapped inside the Parent
class ChildElement extends Component {
  render() {
    return (
      // There are 4 immediate child elements here
      <Parent>
        {/* Wrapping the child elements inside a single element */}
        <div>
          <div>Child 1</div>
          <div>Child 2</div>
          <div>Child 3</div>
          <div>Child 4</div>
        </div>
      </Parent>
    );
  }
}

export default ChildElement;

``` 
Now the output will change to - 

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1624060289686/UomEIKcIB.png)

This is working now as we changed the html structure and added a parent div to the 4 Child elements which will make sure that there is **only one immediate child element** when using the method React.Children.only

## 4. React.Children.map()

#### Scenario 4 - I need to iterate through all the individual child items and then convert this into a button element with a specific style. 

This is again not possible directly via this.props.children.

There is a **map** method provided to us by React.Children which works very similar to the array map method. It returns an array of items as its output.

Let us look at the code below. 

ChildElement.js
```javascript
import { Component } from "react";
import Parent from "./ParentElement";

// This is a simple example for using the Parent component
// And accessing the child elements wrapped inside the Parent
class ChildElement extends Component {
  render() {
    return (
      // There are 4 immediate child elements here
      <Parent>
        {/* Wrapping the child elements inside a single element */}
        <div>
          <div>Child 1</div>
          <div>Child 2</div>
          <div>Child 3</div>
          <div>Child 4</div>
        </div>
      </Parent>
    );
  }
}

export default ChildElement;

``` 
ParentElement.js
```javascript
import React, { Component } from "react";

const btnStyle = {
  background: "green",
  color: "#fff",
  fontSize: "18px",
  fontWeight: "bold",
  border: "1px solid white",
  marginTop: "5px",
  padding: "3px",
};

class ParentElement extends Component {
  render() {
    const { children } = this.props;
    // count method is used to count the immediate child elements in this.props.children
    // Even though the count is 4, we are only displaying Child 1
    return (
      <div>
        <p>
          Total Count of Children: {React.Children.count(this.props.children)}
        </p>
        {/* Making use of the only method */}
        {React.Children.map(children, (child) => {
          return <button style={btnStyle}>{child}</button>;
        })}
      </div>
    );
  }
}

export default ParentElement;

``` 
Output of the above code

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1624060806966/KP0pQrBGZ.png)

Now, if you check this output, we can see that all the 4 Child elements are wrapped inside a single button. This is because in the ChildElement.js we have wrapped all the 4 Child element divs under a single parent div. The **map** method iterates only through the immediate children. 

Now let us change the html structure of ChildElement.js and remove the parent div

```javascript
import { Component } from "react";
import Parent from "./ParentElement";

// This is a simple example for using the Parent component
// And accessing the child elements wrapped inside the Parent
class ChildElement extends Component {
  render() {
    return (
      // There are 4 immediate child elements here
      <Parent>
        {/* Removed the parent div from here */}
        <div>Child 1</div>
        <div>Child 2</div>
        <div>Child 3</div>
        <div>Child 4</div>
      </Parent>
    );
  }
}

export default ChildElement;

``` 
Output for the above code - 

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1624061332088/VHQtmcrle.png)

As we can see in the image, now we get 4 distinct buttons with style applied. 

## 5. React.Children.forEach()

This method is also very similar to the **map** method. The only difference is that it does not return an array. It simply allows the user to iterate over all the immediate child elements. 


```javascript
// This is used to print the values inside the individual child elements 
    React.Children.forEach(children, (child) => {
      console.log(child.props.children);
    });
``` 
Output

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1624061751166/57UePGbt2.png)

I hope this helped to give you a fair understanding of the Children api in react and the common methods available to us and their use cases. 

Happy Coding!