Props, Children, Composition, and Component Purity

React components stay reusable when data flows in through props, layouts accept nested content, and rendering remains predictable.

The mental model

A component is a JavaScript function that returns JSX. Its inputs describe what it should display.

Props

Named inputs passed by a parent.

Children

Content placed between component tags.

Composition

Building features from smaller components.

Purity

Same inputs, same rendered result.

Props are component inputs

A parent passes props with JSX attributes. React gathers them into one object and supplies that object when it calls the component. Props may hold strings, numbers, booleans, objects, arrays, functions, or JSX.

Destructure the prop names in the function parameter so each input is easy to see.
function Profile({ name, role, isOnline }) {
  return (
    <article>
      <h2>{name}</h2>
      <p>{role}</p>
      <span>{isOnline ? "Online" : "Offline"}</span>
    </article>
  );
}

export default function App() {
  return (
    <Profile
      name="Mina"
      role="Frontend developer"
      isOnline={true}
    />
  );
}
  • Quoted attributes are strings.

    name="Mina" passes the string "Mina".

  • Curly braces evaluate JavaScript.

    isOnline={true} passes a boolean, not the string "true".

  • Props are read-only.

    A child must not assign to a prop. If an interaction should change data, the parent can pass state and an event handler.

A default parameter supplies a value only when the prop is missing or undefined.
function Avatar({ name, size = 48 }) {
  return <img src={`/avatars/${name}.png`} alt={name} width={size} />;
}

<Avatar name="mina" />
<Avatar name="leo" size={72} />

Children is a special prop

Content nested inside a component becomes its children prop. A wrapper can decide where that content belongs without needing to know what the content is.

The Panel component owns the surrounding structure while its caller supplies the contents.
function Panel({ title, children }) {
  return (
    <section className="panel">
      <h2>{title}</h2>
      <div className="panel-content">{children}</div>
    </section>
  );
}

export default function App() {
  return (
    <Panel title="Delivery details">
      <p>Arrives on Tuesday.</p>
      <button>Track order</button>
    </Panel>
  );
}

Children can be text, elements, components, lists, or nothing. A self-closing component such as <Panel /> has no nested children. Use named props when the component needs several distinct content areas, such as header, sidebar, and footer.

Composition combines focused pieces

Composition means putting components inside other components. It is React's main reuse mechanism: each piece handles a small responsibility, and a parent arranges the pieces into a feature.

A product card composes an existing button instead of rebuilding its behavior.
function AddToCartButton({ onAdd }) {
  return <button onClick={onAdd}>Add to cart</button>;
}

function ProductCard({ product, onAdd }) {
  return (
    <article>
      <h2>{product.name}</h2>
      <p>₹{product.price}</p>
      <AddToCartButton onAdd={() => onAdd(product.id)} />
    </article>
  );
}
  • Keep leaf components focused.

    A button can own button behavior while a product card owns product presentation.

  • Pass data down.

    The parent provides the values a child needs through props.

  • Pass actions down.

    A function prop lets a child report an interaction without owning the parent's data.

Component purity keeps rendering predictable

A pure component returns the same JSX when its props, state, and context are the same. Rendering should calculate the interface, not change data that existed before the render.

Impure during render

Mutates a variable outside the component, so repeated renders produce different results.

Pure during render

Uses its input to calculate a value without changing anything outside the component.

The first component changes external data. The second derives its label only from props.
// Impure: rendering changes an outside variable.
let guestNumber = 0;

function Guest() {
  guestNumber += 1;
  return <p>Guest #{guestNumber}</p>;
}

// Pure: the same number always produces the same JSX.
function Guest({ number }) {
  const label = `Guest #${number}`;
  return <p>{label}</p>;
}

Local calculation is safe. Creating a new array, object, or variable inside the component does not affect code outside that render. Event handlers may update state because they run in response to an interaction, not while React is rendering.

The design rule: pass information with props, expose flexible space with children, assemble small components through composition, and keep rendering pure.

Check your understanding

  1. What receives the paragraph in <Panel><p>Hello</p></Panel>?
    Show answer

    The children prop receives the paragraph element. Panel can render it with {children}.

  2. Why should a child not change an object it received as a prop?
    Show answer

    Props are read-only inputs. Mutating the object also changes data owned by the parent, making the interface harder to predict. Ask the parent to update it through an event handler instead.

  3. Is calculating const total = price * quantity during render impure?
    Show answer

    No. It only derives a local value from inputs and changes nothing outside the component.