---
id: wiki-2026-0508-compound-components
title: Compound Components
category: 10_Wiki/Topics
status: verified
canonical_id: self
aliases: [Compound Component Pattern, React Compound Components]
duplicate_of: none
source_trust_level: A
confidence_score: 0.95
verification_status: applied
tags: [react, patterns, components, composition, context]
raw_sources: []
last_reinforced: 2026-05-10
github_commit: pending
tech_stack:
language: typescript
framework: react
---
# Compound Components
## 매 한 줄
> **"매 parent 가 매 child 들과 implicit state share — 매 expressive composable API."**. Compound Component Pattern은 React (그리고 Vue/Solid) 에서 `` 류의 declarative API 를 만드는 표준. Radix UI, Headless UI, Ariakit, shadcn/ui 의 dominant pattern. 2026년 React 19 + Server Components 시대에도 그대로 valid.
## 매 핵심
### 매 problem solved
- 단일 monolithic component 의 props explosion (``).
- 매 caller 가 매 children 의 layout/order 를 control 의 X.
- Slot composition 의 부재.
### 매 solution
- Parent 가 Context 로 shared state 의 publish.
- Children 이 Context 를 consume — explicit prop drilling 의 X.
- Children 의 component 가 namespace pattern (`Tabs.Tab`) 또는 separate exports.
### 매 patterns
- **React Context based** (most common 2026).
- **`React.Children` cloning** (legacy, fragile with refs/server components).
- **State reducer** (advanced — caller customizes reducer).
- **`asChild` slot** (Radix — wraps user element).
### 매 응용
1. Tabs, Accordion, Disclosure.
2. Menu, Dropdown, Combobox.
3. Dialog, Drawer, Popover.
4. Form fields with label/error/description.
5. DataTable column children.
## 💻 패턴
### Context-based Tabs
```typescript
import { createContext, useContext, useId, useState } from 'react';
type TabsContextValue = {
activeId: string;
setActiveId: (id: string) => void;
baseId: string;
};
const TabsContext = createContext(null);
function useTabs() {
const ctx = useContext(TabsContext);
if (!ctx) throw new Error('Tabs.* must be used inside ');
return ctx;
}
export function Tabs({
defaultValue,
children,
}: { defaultValue: string; children: React.ReactNode }) {
const [activeId, setActiveId] = useState(defaultValue);
const baseId = useId();
return (
{children}
);
}
function List({ children }: { children: React.ReactNode }) {
return