Master prop drilling, children, and patterns for composable component APIs.
function Greeting({ name, age }) {
return <p>Hello {name}, age {age}</p>;
}
<Greeting name="Alice" age={30} />function Button({ label, onClick, disabled = false }) {
return (
<button onClick={onClick} disabled={disabled}>
{label}
</button>
);
}function Card({ title = "Untitled", content }) {
return <div><h2>{title}</h2><p>{content}</p></div>;
}<Button onClick={() => handleClick()} label="Click me" />function Card({ children, title }) {
return (
<div className="card">
<h2>{title}</h2>
<div className="content">{children}</div>
</div>
);
}
<Card title="Welcome">
<p>This is card content</p>
</Card><Container>
<Header />
<Main />
<Footer />
</Container>function Row({ children }) {
return (
<tr>
{React.Children.map(children, (child, index) => (
<td key={index}>{child}</td>
))}
</tr>
);
}// Level 1
<App user={user}>
// Level 2
<Layout user={user}>
// Level 3
<Sidebar user={user}>
// Level 4
<Profile user={user} />
</Sidebar>
</Layout>
</App>const UserContext = createContext();
<UserContext.Provider value={user}>
<App />
</UserContext.Provider>
function Profile() {
const user = useContext(UserContext);
return <div>{user.name}</div>;
}<Layout sidebar={<Sidebar />}>
<Main />
</Layout>function Page({ header: Header, content: Content, footer: Footer }) {
return (
<>
<Header />
<Content />
<Footer />
</>
);
}
<Page
header={<Header />}
content={<MainContent />}
footer={<Footer />}
/>function DataFetcher({ render }) {
const [data, setData] = useState(null);
useEffect(() => { fetchData().then(setData); }, []);
return render(data);
}
<DataFetcher render={(data) => <List items={data} />} /><Modal>
<Modal.Header>Title</Modal.Header>
<Modal.Body>Content</Modal.Body>
<Modal.Footer>Actions</Modal.Footer>
</Modal>function FormFields({ children, error }) {
return React.Children.map(children, (child) =>
React.cloneElement(child, { error })
);
}function Toggle({ children }) {
const [open, setOpen] = useState(false);
return children({ open, toggle: () => setOpen(!open) });
}
<Toggle>
{({ open, toggle }) => (
<button onClick={toggle}>
{open ? "Close" : "Open"}
</button>
)}
</Toggle>function Button({ label, ...rest }) {
return <button {...rest}>{label}</button>;
}Define the function in the parent component and pass it like any other prop: <Button onClick={handleClick} />. In the child, call it via props.onClick() or destructure it directly.
props.children is implicitly populated by JSX between opening and closing tags, while a named slot prop (e.g., header={<Header />}) must be passed explicitly as an attribute. Use named slots when you need multiple distinct content areas in a component.
Use React Context to provide values deep in the tree without threading props through intermediate components, or restructure with composition — pass the deeply-needed component directly as a prop or children so intermediaries never need to know about it.
Yes: <Component {...props} /> works, but be selective — spreading unknown props onto DOM elements causes warnings and can expose internal state. Destructure what you need and spread only a known rest object, e.g., const { internal, ...rest } = props.
Use destructuring defaults in the function signature: function Card({ title = 'Untitled', size = 'md' }). This is preferred over the legacy Component.defaultProps, which is deprecated in modern React.