Composition, children and slots: fewer props, more flexible components
Prefer composition over configuration: pass children and named slot props instead of dozens of flags, avoid prop drilling by passing elements down, and see how hooks changed the container/presentational split.
Comes up in: React, Low-level design, Machine coding
Learn#
Megha’s Card component has 22 props: title, subtitle, showIcon, iconPosition, footerAlign, hideFooter and more. Every new design needs a new prop, and nobody can remember them all.
Composition means building UI by putting components inside each other, instead of configuring one component with flags. children is the main slot. A slot is any prop that takes elements, such as header or actions, so callers decide what goes there:
import { createElement as h } from "react";
import { renderToStaticMarkup } from "react-dom/server";
const user = { name: "Asha" };
// Drilling: Page → Layout → Header → Avatar, and only Avatar uses user.
const Avatar = ({ user }) => h("img", { alt: user.name });
const HeaderDrilled = ({ user }) => h("header", null, h(Avatar, { user }));
const LayoutDrilled = ({ user, children }) => h("div", null, h(HeaderDrilled, { user }), children);
// Composition: Layout takes the header as a slot; nobody in between needs to know about user.
const Header = ({ children }) => h("header", null, children);
const Layout = ({ header, children }) => h("div", null, header, children);
const drilled = h(LayoutDrilled, { user }, h("main", null, "Orders"));
const composed = h(Layout, { header: h(Header, null, h(Avatar, { user })) }, h("main", null, "Orders"));
console.log(renderToStaticMarkup(drilled));
console.log(renderToStaticMarkup(composed) === renderToStaticMarkup(drilled) ? "same HTML, no drilling" : "different");Output (verified)
<div><header><img alt="Asha"/></header><main>Orders</main></div> same HTML, no drilling
Prop drilling is passing a prop through components that do not use it. Composition removes it: build the element where the data is, and pass the element down.
State
- Layout: user (passes on)
- Header: user (passes on)
- Avatar: user (uses)
Page
empty
Drilled: Page passes user to Layout, Layout passes it to Header, Header passes it to Avatar. Only Avatar uses it.
Read the steps as text
- Drilled: Page passes user to Layout, Layout passes it to Header, Header passes it to Avatar. Only Avatar uses it.
- Adding a field means editing three components that never read it.
- Composed: Page builds <Avatar user={user}/> itself and hands it to Layout's header slot.
- Layout and Header just place what they are given. The same HTML comes out, with no drilling.
Predict#
Predict first
Five levels of components pass theme down, and only the deepest uses it. What should you try first?
Often the middle layers only arrange children. Passing a built element, or using children, removes the drilling with no new mechanism. Context is right when many distant components need the value, but it is not the first tool.
Interview angle#
Say it like this — about 30 seconds
“I prefer composition over configuration: instead of adding props like showIcon or footerAlign, a component accepts children and named slots such as header or actions, and the caller decides what goes in. That also fixes most prop drilling, because the element is built where the data lives and passed down already rendered. If many distant components need the same value, such as theme or the current user, I use context. With hooks, the container and presentational split mostly became custom hooks plus simple components.”
Follow-up How do you avoid prop drilling?
Follow-up Does a slot prop re-render when the parent renders?
Follow-up What replaced container components?
Practice#
Guided
Write a small analysis that finds prop drilling in a component tree.
Done when
- A prop received, unused and passed to a child is reported as “Node.prop”.
- Props a node uses itself are not reported.
- Results come in depth-first order.
Remember#
Try to answer each card before you open it. Then add them to your reviews.
What is prop drilling?
Passing a prop through components that do not use it.
What is a slot prop?
A prop that receives elements, such as header or actions.
First fix for drilling?
Composition: build the element where the data is and pass it down.
What replaced most container components?
Custom hooks.
Go deeper
Four layers. Stop at the one your interview needs; each ends with a quick check.
The core ideaEvery round
Check yourself: What is composition over configuration?
Accept children and slots instead of many flag props.
How it works underneathSenior rounds
children is a normal prop; JSX nested inside a component is assigned to it. Any prop can hold elements, so a component can have several named slots.
Check yourself: Are children a special mechanism?
No. children is a normal prop holding elements.
Edge cases and trapsWhere people slip
Children created in the parent are new elements on every parent render, so memo on a component that takes children rarely helps (RCT.03.04). Slots also make it harder for a component to control its children’s props; that is the trade-off of flexibility.
Check yourself: Why might a memo component with children still re-render?
The children elements are new objects each parent render.
In productionStaff-level answers
Check yourself: When is context better than composition?
When many components at different depths need the same value.
Finished the five steps? Mark it, and its cards join your reviews.
Last checked 2026-11-01. Spot a mistake? Use “Report an error” below — fixes are listed on the corrections page.
Interview questions this answers
- How do you avoid prop drilling?