Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що таке "Smart" і "Dumb" компоненти?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Container-Presentational Pattern** ділить компоненти на два типи: контейнер відповідає за логіку, дані та стан, а презентаційний компонент відповідає лише за відображення UI; поняття **"Smart"** і **"Dumb"** компонентів - це більш неформальна, але дуже популярна версія цього самого патерна. **Ключове:** "Smart thinks, Dumb shows" - розумний компонент керує потоком даних (стан, запити, бізнес-логіка), а "глупий" відповідає лише за чистий UI на основі `props`, що робить його легко тестованим і придатним для повторного використання.Показується над повною відповіддю для швидкого нагадування.Відповідь (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` знає **як це показати**. --- Поняття **"Smart"** і **"Dumb"** компонентів (розумні й глупі) - це більш неформальна, але дуже популярна версія **патерна "Container-Presentational"**, про яку ти щойно запитував. Розберемося покроково. --- ## Суть ідеї React-застосунки складаються з двох типів компонентів: | Тип компонента | Що робить | |---|---| | **Smart (розумний)** | Керує логікою, станом, запитами і даними | | **Dumb (глупий)** | Відповідає лише за відображення (UI), не "думає" | > "Smart thinks, Dumb shows" - *розумний думає, глупий показує.* --- ## Приклад ### Dumb Component (презентаційний) Просто отримує дані і рендерить їх. ```javascript function UserCard({ name, age }) { return ( <div className="card"> <h2>{name}</h2> <p>Вік: {age}</p> </div> ); } ``` Особливості: - Не має стану (`useState`, `useEffect`) - Не знає, звідки прийшли дані - Легко тестувати і повторно використовувати - Залежить лише від `props` --- ### Smart Component (контейнер) Відповідає за бізнес-логіку і дані. ```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} age={user.age} />; } ``` Особливості: - Керує станом і логікою - Робить запити до API - Обробляє події - Передає дані вниз через props --- ## Відмінності в таблиці | Характеристика | Smart компонент | Dumb компонент | |---|---|---| | Керує станом | Так | Ні | | Робить запити | Так | Ні | | Знає бізнес-логіку | Так | Ні | | Рендерить UI | Частково | Основне | | Приймає props | Так | Так | | Придатний для повторного використання | Не завжди | Легко | | Тестується | Складніше | Просто | | Приклади | Containers, Hooks, Providers | Buttons, Cards, Modals | --- ## Зв'язок між ними ```javascript Smart └── Dumb └── (ще дрібніші Dumb) ``` > Розумний компонент керує потоком даних, > а "глупі" відповідають за чистий UI. --- ## Чому це зручно Код чистіший: логіка не перемішана з версткою Легше тестувати UI окремо UI-компоненти стають придатними для повторного використання Можна змінювати дизайн без зміни логіки Можна використовувати ті самі Dumb-компоненти в різних частинах застосунку --- ## Сучасна еволюція Сьогодні в React (особливо з хуками і Next.js 13+) цей патерн часто реалізується не буквально як "Smart/Dumb компоненти", а через **розділення на:** - **Hooks (розумні)** - `useUser()`, `useTodos()`, `useCart()` - **UI компоненти (глупі)** - `UserCard`, `TodoList`, `CartItem` Приклад: ```javascript // useUser.js export function useUser() { const [user, setUser] = useState(null); useEffect(() => { fetch('/api/user') .then(r => r.json()) .then(setUser); }, []); return user; } // UserCard.jsx export function UserCard({ user }) { return ( <div>{user?.name ?? 'Завантаження...'}</div> ); } // Page.jsx import { useUser } from './useUser'; import { UserCard } from './UserCard'; export default function Page() { const user = useUser(); return <UserCard user={user} />; } ``` > Тепер "розум" знаходиться в хуку, а "глупість" - в UI-компоненті. > Це сучасний спосіб реалізувати той самий патерн. --- ## Підсумок | Поняття | Що означає | |---|---| | **Smart Component** | Компонент, який керує логікою, станом і даними | | **Dumb Component** | Компонент, який просто відображає UI на основі props | | **Патерн вирішує** | Розділення відповідальності і покращення архітектури | | **Сучасний аналог** | Хуки + UI-компоненти |Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.