Home
React
Patterns: Compound Components
Daniel Nguyen
Daniel Nguyen
July 21, 2025
1 min

The Compound Components Pattern lets related components share internal state while exposing a flexible, declarative API.

1. Problem: Too Many Props

A traditional component requires consumers to manage and pass state explicitly.

<Toggle
on={on}
onToggle={toggle}
/>

As the component grows, its API can become harder to manage. Consumers may need to coordinate multiple props to control related UI elements.

2. Solution: Compound Components

Compound components let consumers compose related components under a common parent.

<Toggle>
<Toggle.On>ON</Toggle.On>
<Toggle.Off>OFF</Toggle.Off>
<Toggle.Button />
</Toggle>

The parent manages the shared state, while its children access that state implicitly through React Context.

3. How Does It Work?

The parent provides the state through Context. Child components consume it using useContext.

import {
createContext,
useContext,
useState,
type ReactNode,
} from "react";
type ToggleContextValue = {
on: boolean;
toggle: () => void;
};
const ToggleContext = createContext<ToggleContextValue | undefined>(
undefined
);
function useToggle() {
const context = useContext(ToggleContext);
if (!context) {
throw new Error("Toggle components must be used within <Toggle>");
}
return context;
}
function Toggle({ children }: { children: ReactNode }) {
const [on, setOn] = useState(false);
const toggle = () => setOn(value => !value);
return (
<ToggleContext.Provider value={{ on, toggle }}>
{children}
</ToggleContext.Provider>
);
}
function On({ children }: { children: ReactNode }) {
const { on } = useToggle();
return on ? children : null;
}
function Off({ children }: { children: ReactNode }) {
const { on } = useToggle();
return on ? null : children;
}
function Button() {
const { on, toggle } = useToggle();
return (
<button type="button" onClick={toggle} aria-pressed={on}>
{on ? "Turn off" : "Turn on"}
</button>
);
}
Toggle.On = On;
Toggle.Off = Off;
Toggle.Button = Button;
export { Toggle };

Usage:

<Toggle>
<Toggle.On>The toggle is ON</Toggle.On>
<Toggle.Off>The toggle is OFF</Toggle.Off>
<Toggle.Button />
</Toggle>

Tags

#ReactPatterns

Share

Daniel Nguyen

Daniel Nguyen

Frontend Developer

Frontend developer specializing in React, Next.js, and JavaScript. Writing practical guides on modern web development at Dev98.

Expertise

React
Next.js
JavaScript
TypeScript
Python

Social Media

githublinkedinyoutubewebsite

Related Posts

Advanced React Patterns
Patterns: Latest Ref
July 23, 2025
1 min
Dev98

Dev98

React · Next.js · Web development