typescriptadvanced
React Compound Component Pattern
Build flexible compound components using React context for shared state between related parts.
typescriptPress ⌘/Ctrl + Shift + C to copy
import { createContext, useContext, useState, ReactNode } from 'react';
// Accordion compound component
interface AccordionContextType {
activeId: string | null;
toggle: (id: string) => void;
}
const AccordionContext = createContext<AccordionContextType | null>(null);
function useAccordion() {
const ctx = useContext(AccordionContext);
if (!ctx) throw new Error('Must be used within Accordion');
return ctx;
}
function Accordion({ children }: { children: ReactNode }) {
const [activeId, setActiveId] = useState<string | null>(null);
const toggle = (id: string) => setActiveId((prev) => (prev === id ? null : id));
return (
<AccordionContext.Provider value={{ activeId, toggle }}>
<div className="divide-y divide-white/10">{children}</div>
</AccordionContext.Provider>
);
}
function AccordionItem({ id, children }: { id: string; children: ReactNode }) {
return <div data-id={id}>{children}</div>;
}
function AccordionTrigger({ id, children }: { id: string; children: ReactNode }) {
const { activeId, toggle } = useAccordion();
return (
<button
className="w-full p-4 text-left flex justify-between"
onClick={() => toggle(id)}
>
{children}
<span>{activeId === id ? '−' : '+'}</span>
</button>
);
}
function AccordionContent({ id, children }: { id: string; children: ReactNode }) {
const { activeId } = useAccordion();
if (activeId !== id) return null;
return <div className="p-4 pt-0">{children}</div>;
}
// Attach sub-components
Accordion.Item = AccordionItem;
Accordion.Trigger = AccordionTrigger;
Accordion.Content = AccordionContent;
// Usage
function FAQ() {
return (
<Accordion>
<Accordion.Item id="q1">
<Accordion.Trigger id="q1">What is React?</Accordion.Trigger>
<Accordion.Content id="q1">A UI library.</Accordion.Content>
</Accordion.Item>
<Accordion.Item id="q2">
<Accordion.Trigger id="q2">Why use TypeScript?</Accordion.Trigger>
<Accordion.Content id="q2">Type safety.</Accordion.Content>
</Accordion.Item>
</Accordion>
);
}Use Cases
- Building flexible component libraries
- Accordion, tabs, and dropdown patterns
- Sharing state between related sub-components
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
typescriptadvanced
Context Selector Pattern
Avoid unnecessary re-renders with a context selector pattern that subscribes to specific state slices.
Best for: High-performance global state
#react#context
typescriptadvanced
Compound Component Pattern
Build flexible compound components using React Context for implicit parent-child communication.
Best for: Accordion components
#patterns#compound-component
typescriptintermediate
React useReducer for Complex State
Manage complex component state with useReducer pattern including typed actions and middleware.
Best for: Shopping cart state management
#react#useReducer
typescriptadvanced
Suspense Data Fetching Pattern
Use React Suspense for data fetching with resource caching, error boundaries, and streaming SSR.
Best for: Suspense-first data loading
#react#suspense