Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що таке "Container-Presentational Pattern"?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Container-Presentational Pattern** ділить компоненти на два типи: **Container** відповідає за логіку, дані й стан, а **Presentational** - лише за відображення UI. **Ключове:** "контейнер думає, а презентаційний показує", завдяки чому UI можна замінити без зміни бізнес-логіки й повторно використовувати з різними джерелами даних.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Суть патерну **Container-Presentational Pattern** ділить компоненти на два типи: | Тип | Призначення | |---|---| | **Container (контейнер)** | Відповідає за **логіку, дані та стан** | | **Presentational (презентаційний)** | Відповідає лише за **відображення UI** | > Ідея: **"контейнер думає, а презентаційний показує"** --- ## Приклад ### Presentational Component Він отримує дані через `props` і просто їх відображає. ```javascript function UserCard({ name, age }) { return ( <div className="card"> <h2>{name}</h2> <p>Вік: {age}</p> </div> ); } ``` > Не містить стану > Не робить запитів > Не знає, звідки приходять дані > → чистий UI-компонент --- ### Container Component Він керує станом і логікою та передає дані вниз. ```javascript function UserCardContainer() { 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} age={user.age} />; } ``` > Отримує дані > Керує станом > Викликає побічні ефекти > Передає дані в презентаційний компонент --- ## Навіщо це потрібно | Проблема | Рішення через патерн | |---|---| | Логіка і UI змішані в одному компоненті → важко читати | Розділяємо: один думає, інший показує | | Важко тестувати і повторно використовувати | Презентаційні легко тестувати й використовувати повторно | | Потрібно відобразити той самий UI з різними джерелами даних | Можна використати один `Presentational`, а різні `Container` | | Під час редизайну ламається логіка | UI можна замінити без зміни бізнес-логіки | --- ## Архітектурно ```javascript Container (логіка) └── Presentational (UI) ``` Наприклад: ```javascript UserListContainer └── UserList └── UserCard ``` --- ## Типові ознаки | Ознака | Container | Presentational | |---|---|---| | Тримає стан | Так | Ні | | Використовує хуки (`useState`, `useEffect`) | Так | Рідко | | Робить запити до API | Так | Ні | | Знає про бізнес-логіку | Так | Ні | | Приймає props для відображення | Так | Так | | Визначає розмітку і стилі | Ні | Так | --- ## Приклад у сучасній архітектурі (React + Redux) ```javascript // Presentational.jsx export function TodoList({ todos, onToggle }) { return ( <ul> {todos.map(todo => ( <li key={todo.id} onClick={() => onToggle(todo.id)} style={{ textDecoration: todo.done ? 'line-through' : 'none' }} > {todo.text} </li> ))} </ul> ); } ``` ```javascript // Container.jsx import { useSelector, useDispatch } from 'react-redux'; import { toggleTodo } from '../store/todoSlice'; import { TodoList } from './Presentational'; export function TodoListContainer() { const todos = useSelector(state => state.todos); const dispatch = useDispatch(); return ( <TodoList todos={todos} onToggle={(id) => dispatch(toggleTodo(id))} /> ); } ``` --- ## У сучасному React Хоча патерн родом з епохи **класових компонентів**, він **все ще актуальний** - просто реалізується через хуки й композицію. Тепер "контейнером" може бути: - хук (`useUser`, `useTodos`) - компонент-обгортка - контекст-провайдер --- ## Підсумок | Що | Опис | |---|---| | Ідея | Розділити "логіку" і "відображення" | | Container | Отримує й обробляє дані | | Presentational | Показує інтерфейс | | Користь | Повторне використання, читабельність, тестованість | | Сучасний аналог | Хуки + Dumb/UI компоненти | --- > **Підсумкова формула:** > `Container` знає **що показати**, > `Presentational` знає **як це показати**.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.