Композиція компонентів
Що таке "композиція компонентів"
Композиція компонентів (component composition) - це спосіб збирати інтерфейс із незалежних, переюзабельних блоків, комбінуючи їх один з одним як конструктор LEGO.
Іншими словами:
Один компонент може включати, обгортати або вбудовувати інші компоненти, формуючи складний UI.
Приклад композиції
1. Базовий компонент
function Card({ children }) {
return <div className="card">{children}</div>;
}2. Використання через композицію
<Card>
<h2>Заголовок</h2>
<p>Опис картки</p>
</Card>Тут
Cardне знає, що саме всередині. Він просто "контейнер", а контент вставляється черезchildren. Це і є композиція - об'єднання компонентів через включення один в одного.
Композиція замість успадкування
Успадкування (класичний ООП-підхід)
Якби React був побудований на успадкуванні, довелося б робити так:
class SpecialButton extends Button {
render() {
return <button style={{ color: "red" }}>{this.props.label}</button>;
}
}Тобто "розширювати" наявний компонент. Це жорстко зв'язує компоненти: якщо базовий зміниться, може зламатися нащадок.
Композиція (React-підхід)
function Button({ children, ...props }) {
return <button {...props}>{children}</button>;
}
function SpecialButton() {
return <Button style={{ color: "red" }}>Натисни</Button>;
}Ми використовуємо компонент усередині іншого, замість того щоб від нього успадковуватися. Це дає більше гнучкості і менше зв'язків.
Чому React обрав композицію
| Причина | Пояснення |
|---|---|
| Гнучкість | Можна комбінувати компоненти в будь-яких структурах |
| Ізоляція | Кожен компонент незалежний, не знає деталей інших |
| Переюзабельність | Один компонент можна вставляти в різні контексти |
| Ясний інтерфейс | Компонент керує лише своїми props і children |
| Менше зв'язків | Немає жорсткої ієрархії класів (на відміну від ООП) |
| Композиція = декларативність | "Я описую, що включено в що", а не "який клас розширює який" |
Типи композиції в React
1. Через children
Найбазовіший спосіб:
<Layout>
<Sidebar />
<Content />
</Layout>→ компонент <Layout> рендерить props.children.
2. Через пропси-компоненти
Можна передавати конкретні "слоти":
function Dialog({ title, footer, children }) {
return (
<div className="dialog">
<h2>{title}</h2>
<div>{children}</div>
<footer>{footer}</footer>
</div>
);
}
<Dialog
title="Видалити акаунт?"
footer={<button>Так, видалити</button>}
>
<p>Цю дію не можна скасувати.</p>
</Dialog>Такий спосіб часто називають "slot pattern" - коли всередину компонента можна вставляти різні частини інтерфейсу.
3. Через Compound Components
(складніший варіант композиції):
<Accordion>
<Accordion.Item>
<Accordion.Header>Питання</Accordion.Header>
<Accordion.Panel>Відповідь</Accordion.Panel>
</Accordion.Item>
</Accordion>Тут уся логіка в
Accordion, але розробник сам композиційно будує UI.
4. Через render-props
(ще один спосіб композиції через функції):
<DataProvider render={(data) => <Chart data={data} />} />Чому композиція краща за успадкування
| Критерій | Композиція | Успадкування |
|---|---|---|
| Розширення поведінки | Через вкладення і props | Через extends |
| Гнучкість структури | Дуже висока | Жорстка ієрархія |
| Ізоляція | Компоненти незалежні | Класи пов'язані |
| Переюзабельність | Відмінна | Обмежена |
| Ризик поломки | Мінімальний | Високий (при зміні базового класу) |
| Підхід у React | Пріоритетний | Не використовується |
Метафора
- Композиція = LEGO: можна зібрати що завгодно з незалежних блоків.
- Успадкування = ДНК: якщо змінити "батька" - ламаються всі "нащадки".
Підсумок
| Що | Опис |
|---|---|
| Композиція | Об'єднання компонентів шляхом включення їх один в одного |
| Мета | Переюзабельність і гнучкість без жорстких зв'язків |
| Приклад | <Card><Header /><Body /></Card> |
| Перевага | Ізоляція, читабельність, масштабованість |
| Успадкування | Занадто жорстке і не підходить під декларативну модель React |
Головна думка: React-компоненти не успадковуються - вони компонуються.
Замість "створити новий клас від старого" → ти "вставляєш компонент в інший". Це і робить React декларативним, передбачуваним і гнучким.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.