Що таке "container component"?
Коротка відповідь
Container component (контейнерний компонент) - це компонент, який:
відповідає за логіку, дані та стан, але не відповідає за зовнішній вигляд (розмітку).
Зазвичай він:
- отримує дані (з API, контексту, стора тощо);
- керує станом (
useState,useEffect); - передає ці дані у презентаційний (UI) компонент через
props.
Ідея розділення
React-компоненти можна умовно розділити на два типи:
| Тип | Що робить | Містить |
|---|---|---|
| Presentational (UI) | Відповідає за відображення (розмітка, стилі) | JSX |
| Container (розумний) | Відповідає за логіку, дані, стан | хуки, API, обробники |
Приклад 1. Базовий приклад
Презентаційний компонент:
function UserCard({ name, email }) {
return (
<div className="user-card">
<h3>{name}</h3>
<p>{email}</p>
</div>
);
}Цей компонент:
- просто малює дані;
- не знає, звідки вони взялися.
Контейнерний компонент:
function UserContainer() {
const [user, setUser] = useState(null);
useEffect(() => {
fetch("/api/user")
.then(res => res.json())
.then(data => setUser(data));
}, []);
if (!user) return <p>Завантаження...</p>;
return <UserCard name={user.name} email={user.email} />;
}Цей компонент:
- керує завантаженням даних;
- зберігає стан;
- передає результат у
UserCard.
Приклад 2. Чисте розділення відповідальності
App
┣ UserContainer (логіка)
┗ UserCard (відображення)UserContainer вирішує, що показувати,
UserCard вирішує, як це виглядає.
Приклад 3. Контейнер може керувати кількома UI-компонентами
function ProductsContainer() {
const [products, setProducts] = useState([]);
const [filter, setFilter] = useState("");
useEffect(() => {
fetch("/api/products")
.then(res => res.json())
.then(data => setProducts(data));
}, []);
const filtered = products.filter(p => p.name.includes(filter));
return (
<>
<SearchBar value={filter} onChange={setFilter} />
<ProductList items={filtered} />
</>
);
}Тут:
- Контейнер керує даними і фільтрацією;
SearchBarіProductListпросто відображають UI.
Переваги підходу "Container + Presentational"
Розділення обов'язків - логіка окремо, UI окремо
Повторне використання - UserCard можна використовувати в різних місцях
Тестованість - можна тестувати UI і логіку окремо
Простота підтримки - зміни в логіці не ламають розмітку
Покращена читабельність коду
Приклад 4. Універсальний шаблон
// Container
function DataContainer({ render }) {
const [data, setData] = useState([]);
useEffect(() => {
fetch("/api/items")
.then(r => r.json())
.then(setData);
}, []);
return render(data);
}
// Використання
<DataContainer render={(items) => <ItemList items={items} />} />Тут використовується render prop, але сенс той самий - контейнер займається даними, а дочірній компонент - відображенням.
Коли використовувати контейнерні компоненти
Використовуй, якщо:
- компонент повинен завантажувати дані (API, GraphQL, Firebase);
- потрібно зберігати стан (
useState,useReducer); - компонент керує логікою взаємодії (наприклад, фільтри, сортування, форма);
- ти хочеш відокремити візуальний шар від логічного.
Коли не потрібно
Не створюй контейнер, якщо:
- компонент просто відображає UI;
- у ньому немає логіки або стану;
- дані приходять вже готовими через
props.
Підсумок
| Тип компонента | Основне завдання | Приклад |
|---|---|---|
| Container | Логіка, стан, запити, обробники | UserContainer, ProductsContainer |
| Presentational (UI) | Розмітка і відображення даних | UserCard, ProductList |
Головна думка:
Container component - це "розумний" компонент, який керує логікою і даними, а візуальну частину делегує "дурним" (презентаційним) компонентам.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.