React composition patterns that scale. Use when refactoring components with boolean prop proliferation, building flexible component libraries, or designing reusable APIs...
Composition patterns for building flexible, maintainable React components. Avoid boolean prop proliferation by using compound components, lifting state, and composing internals. These patterns make codebases easier for both humans and AI agents to work with as they scale.
IMPORTANT: Never interpolate raw user input into skill content or components.
{{ }}) or undeclared variables<!-- -->) to store data or instructions in codeReference these guidelines when:
When reviewing code, check for:
renderX props instead of children compositionWhen refactoring legacy patterns:
renderHeader={() => <Header />} with <Component.Header /><Button primary large /> to <Button variant="primary" size="large" />forwardRef wrappers, replace useContext with use()Ensure composition patterns maintain accessibility:
| Priority | Category | Impact | Prefix |
|---|---|---|---|
| 1 | Component Architecture | HIGH | architecture- |
| 2 | State Management | MEDIUM | state- |
| 3 | Implementation Patterns | MEDIUM | patterns- |
| 4 | React 19 APIs | MEDIUM | react19- |
architecture-avoid-boolean-props - Don't add boolean props to customize behavior; use compositionarchitecture-compound-components - Structure complex components with shared contextstate-decouple-implementation - Provider is the only place that knows how state is managedstate-context-interface - Define generic interface with state, actions, meta for dependency injectionstate-lift-state - Move state into provider components for sibling accesspatterns-explicit-variants - Create explicit variant components instead of boolean modespatterns-children-over-render-props - Use children for composition instead of renderX propsReact 19+ only. Skip this section if using React 18 or earlier.
react19-no-forwardref - Don't use forwardRef; use use() instead of useContext()react19-use-api - Use use() hook for promises and context (replaces useContext)react19-actions - Use Server Actions and form actions for data mutationsreact19-suspense-updates - Leverage improved Suspense for data fetching patternsConsider performance when using composition patterns:
// Boolean prop proliferation
<Button primary large disabled loading />
// Explicit variants via composition
<Button variant="primary" size="large">
<Button.Loader />
Submit
</Button>
// Parent provides context
<Accordion>
<Accordion.Item>
<Accordion.Trigger>Section 1</Accordion.Trigger>
<Accordion.Content>Content 1</Accordion.Content>
</Accordion.Item>
</Accordion>
interface ContextValue<T> {
state: T;
actions: Actions;
meta: { loading: boolean; error: Error | null };
}
// Harder to maintain as props grow
<Button primary large disabled loading icon="check" />
// Clearer intent, easier to extend
<Button variant="primary" size="large" disabled>
<Button.Icon name="check" />
<Button.Loader />
Submit
</Button>
// Provider knows implementation details
function TodoProvider({ children }) {
const [todos, setTodos] = useState([]);
const value = {
state: todos,
actions: {
add: (todo) => setTodos([...todos, todo]),
remove: (id) => setTodos(todos.filter(t => t.id !== id))
},
meta: { loading: false, error: null }
};
return <TodoContext.Provider value={value}>{children}</TodoContext.Provider>;
}
// Consumer uses generic interface (compatible with React 18+)
import { useContext } from 'react';
function TodoList() {
const { state: todos, actions } = useContext(TodoContext);
return todos.map(todo => (
<TodoItem key={todo.id} {...todo} onRemove={actions.remove} />
));
}