Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що таке "container component"?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Container component** (контейнерний компонент) - це компонент, який відповідає за логіку, дані та стан, але не відповідає за зовнішній вигляд (розмітку). **Ключове:** він отримує дані (з API, контексту, стора тощо), керує станом (`useState`, `useEffect`) і передає ці дані в презентаційний (UI) компонент через `props`.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Коротка відповідь **Container component** (контейнерний компонент) - це компонент, який: > **відповідає за логіку, дані та стан**, > але **не відповідає за зовнішній вигляд (розмітку)**. Зазвичай він: - отримує дані (з API, контексту, стора тощо); - керує станом (`useState`, `useEffect`); - передає ці дані **у презентаційний (UI) компонент** через `props`. --- ## Ідея розділення React-компоненти можна умовно розділити на два типи: | Тип | Що робить | Містить | |---|---|---| | **Presentational (UI)** | Відповідає за відображення (розмітка, стилі) | JSX | | **Container (розумний)** | Відповідає за логіку, дані, стан | хуки, API, обробники | --- ## Приклад 1. Базовий приклад ### Презентаційний компонент: ```javascript function UserCard({ name, email }) { return ( <div className="user-card"> <h3>{name}</h3> <p>{email}</p> </div> ); } ``` Цей компонент: - просто **малює дані**; - не знає, звідки вони взялися. --- ### Контейнерний компонент: ```javascript 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. Чисте розділення відповідальності ```javascript App ┣ UserContainer (логіка) ┗ UserCard (відображення) ``` `UserContainer` вирішує, **що показувати**, `UserCard` вирішує, **як це виглядає**. --- ## Приклад 3. Контейнер може керувати кількома UI-компонентами ```javascript 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. Універсальний шаблон ```javascript // 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** - це "розумний" компонент, > який керує логікою і даними, > а візуальну частину делегує "дурним" (презентаційним) компонентам.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.