React  

Using children in React?

Introduction

In the last article, we learned how to pass data using props, passing values to a child component through attributes. But what if you want to pass not just data, but actual content like elements, text, or even other components between a component's opening and closing tags?

That's where children come in.

The children prop is a special built-in feature in React that allows components to receive and render whatever is nested inside them. It opens the door to more flexible and reusable UI patterns for building layout wrappers, modals, cards, and more.

In this article, we'll dive into how children work, how to access and use them effectively, and when they can be more powerful than regular props.

What are props.children?

Simply put, children refer to the content you put between a component’s opening and closing tags.

<!-- Syntax -->
<MyWrapper>
  <p>This is a child element!</p>
</MyWrapper>

Here, <p>This is a child element!</p> is what we call props.children inside the MyWrapper component.

How to Use Children?

Parent component (App.js)

import './App.css';
import MyWrapper from './components/Wrapper';

function App() {
  return (
    <div>
      <h1>This is parent component</h1>
      <MyWrapper>
        <p>This is wrapped content sent from parent component.</p>
      </MyWrapper>
    </div>
  );
}
export default App;

Child component (Wrapper.js)

// Child component

const MyWrapper = (props) => {
  return (
    <div>
      {props.children}
    </div>
  );
};

export default MyWrapper;

And this is how it looks.

Parent component

Different Ways to Use Children
 

1. Basic JSX children(this one we saw above)

// Child Component
const Card = (props) => {
  return (
    <div>
      <h1>Child: Card</h1>
      {props.children}
    </div>
  );
};

// Parent Component
function App() {
  return (
    <div>
      <h1>This is parent component</h1>
      <Card>
        <h2>Alex</h2>
        <p>Age: 27</p>
        <p>Profession: Engineer</p>
      </Card>
    </div>
  );
}

Card

Or you can also use Destructuring,

Note. In React, children is a special prop, i.e. reserved property in the React ecosystem.

const Card = ({ children }) => {
  return (
    <div>
      <h1>Child: Card</h1>
      {children}
    </div>
  );
};

2. Render with a fallback

const Alert = ({ children, type }) => {
  const typeStyles = {
    success: {
      border: "1px solid #28a745",
      backgroundColor: "#d4edda",
      color: "#155724",
    },
    warning: {
      border: "1px solid #ffc107",
      backgroundColor: "#fff3cd",
      color: "#856404",
    },
    error: {
      border: "1px solid #dc3545",
      backgroundColor: "#f8d7da",
      color: "#721c24",
    },
    info: {
      border: "1px solid #17a2b8",
      backgroundColor: "#d1ecf1",
      color: "#0c5460",
    },
    default: {
      border: "1px solid #ccc",
      backgroundColor: "#fff",
      color: "#000",
    },
  };

  const style = {
    ...typeStyles[type] || typeStyles.default,
  };

  return (
    <div style={style}>
      {children ? children : "Default alert message."}
    </div>
  );
};

export default Alert;

I am using a fallback in two places.

Content fallback

This ensures that if no content (children) is passed to the <Alert> component, it still shows a meaningful default message. This will happen in the case of info.

{children ? children : "Default alert message."}

Fallback for type

(typeStyles[type] || typeStyles.default)

Here, we're dynamically applying styles based on the type prop. If type is not provided, or it's not one of the predefined ones (success, error, etc.), it falls back to the "default" style.

This is how I am calling the Alert-component.

<Alert type="success">
  Your form was submitted successfully!
</Alert>

<Alert type="warning">
  Please check your inputs!
</Alert>

<Alert type="error">
  Something went wrong.
</Alert>

<Alert type="info" />

Component

As you can see, type=info takes the default style and the default message.

3. Use the first or last child only

const Wrapper = ({ children, position = "first" }) => {
  const childrenArray = React.Children.toArray(children);
  const content = position === "last" 
    ? childrenArray[childrenArray.length - 1] 
    : childrenArray[0];
  return (
    <div>
      <h3>{position === "last" ? "Last Child:" : "First Child:"}</h3>
      {content}
    </div>
  );
};

export default Wrapper;

<Wrapper position="first">
  <p>First child</p>
  <p>Second child</p>
  <p>Third child</p>
</Wrapper>

<Wrapper position="last">
  <p>First child</p>
  <p>Second child</p>
  <p>Third child</p>
</Wrapper>

Last but not least:cloneElement
 

Why Use cloneElement?

  • To inject props (like style, className, onClick, etc.) into children.
  • To apply shared behavior or styling to any nested components.
  • To avoid modifying the original child components directly.
import React, { cloneElement } from "react";

const Message = ({ text, color }) => {
  return <p style={{ color }}>{text}</p>;
};
const ColorWrapper = ({ children }) => {
  return cloneElement(children, { color: "green" });
};
function App() {
  return (
    <div>
      <ColorWrapper>
        <Message text="This is a green message!" />
      </ColorWrapper>
    </div>
  );
}
export default App;

What’s Happening?

  • <Message /> expects a text and color.
  • Instead of giving color directly, we let ColorWrapper inject it.
  • cloneElement(children, { color: "green" }) adds the color prop to <Message />.

Children vs Named Props
 

Use Case children Named Props
JSX, HTML, components Best Fit Less Flexible
Strings, small values Use Sparingly Best Fit


Mistakes to Avoid
 

Mistake Problem
Not rendering children The component shows nothing
Assuming it's always an array Could be a single element or a string
Modifying children directly Breaks immutability — use cloneElement
Forgetting wrapper elements JSX must return a single root


Conclusion

Children make your components more flexible. It's perfect for layouts, wrappers, and any situation where you want to plug in different JSX without changing the component itself.

Once you get the hang of it, you’ll find yourself using children all the time to build clean, reusable UIs.