Compound components

Тема дорожной карты · React

Compound Components — это продвинутый паттерн React, при котором набор компонентов работает совместно, разделяя неявное состояние и формируя целостный UI, — аналогично тому, как HTML-элементы <select> и <option> взаимодействуют друг с другом. В этом паттерне родительский компонент управляет разделяемым состоянием через useContext или React.cloneElement, а дочерние компоненты — вкладки, элементы, панели — читают из этого контекста без явного проброса пропсов. Compound Components дают фронтенд-разработчикам гибкий и выразительный API: потребители свободно компонуют подкомпоненты, тогда как детали реализации инкапсулированы внутри родителя. Библиотеки Headless UI и Radix UI построены на паттерне Compound Components для предоставления доступных, стилистически нейтральных React-примитивов. Освоение Compound Components — ключевой шаг к созданию профессиональных React-дизайн-систем и переиспользуемых библиотек компонентов.

Как это работает

Compound components покрывает переиспользуемые техники композиции: Compound Components (родитель + дети делят state через Context — <Tabs><TabList><Tab/></TabList></Tabs>), Render Props (компонент принимает функцию, возвращающую JSX — <X>{value => <Y v={value}/>}</X>), Higher-Order Components (функция, оборачивающая компонент — withAuth(Page)), Portals (рендер в другое поддерево DOM через createPortal), Error Boundaries (классовые компоненты, ловящие render-ошибки через componentDidCatch).

Когда применять

Compound Components — для UI-примитивов, где родитель + дети делят контракт (Tabs, Accordion, Select). Portals — для модалок, тултипов, toast, которым нужно сбежать из overflow:hidden или stacking context. Оборачивайте всё приложение (и рискованные поддеревья) в Error Boundary — иначе брошенная render-ошибка обнуляет страницу. Render Props и HOC в основном вытеснены хуками; берите их только в legacy-библиотеках.

Типичные ошибки

Ловушки Compound components: переизобретение Compound Components, когда react-aria или Radix уже дают accessible-примитивы; Portal-контент теряет Context родительского React-дерева (portal формально в дереве, но если забыли — accessibility ломается); Error Boundaries, тихо съедающие ошибки без логирования (никогда о них не узнаёте); HOC-пирамида (withA(withB(withC(Page))) — хуки заменили). Используйте готовые библиотеки перед своими абстракциями.

Связанные понятия

Полезные ресурсы