Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «SRP в React-компонентах». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Single Responsibility Principle** - принцип *єдиної відповідальності*: "У модуля повинна бути одна і тільки одна причина для зміни" (за Робертом Мартіном, автором SOLID). У React цей "модуль" - **компонент**, і React-компонент повинен робити тільки одну річ - і робити її добре. **Ключове:** якщо компонент керує і логікою, і зовнішнім виглядом, і даними, і API - він порушує SRP.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Що таке SRP (у загальному вигляді) **Single Responsibility Principle** - принцип *єдиної відповідальності*. > Формулювання (за Робертом Мартіном, автором SOLID): > "У модуля повинна бути одна і тільки одна причина для зміни." У React цей "модуль" - **компонент**. Якщо компонент робить **занадто багато**, то: - його важко зрозуміти; - його важко тестувати; - будь-яка зміна може непередбачувано вплинути на інші частини UI. --- ## SRP у React: просте визначення > **React-компонент повинен робити тільки одну річ - і робити її добре.** Тобто: - Один компонент = одна відповідальність. - Якщо компонент керує і логікою, і зовнішнім виглядом, і даними, і API - він порушує SRP. --- ## Приклад порушення SRP (поганий код) ```javascript function UserProfile() { const [user, setUser] = useState(null); useEffect(() => { fetch('/api/user') .then(res => res.json()) .then(setUser); }, []); const handleDelete = async () => { await fetch(`/api/user/${user.id}`, { method: 'DELETE' }); setUser(null); }; if (!user) return <div>Loading...</div>; return ( <div> <h1>{user.name}</h1> <button onClick={handleDelete}>Видалити користувача</button> </div> ); } ``` Проблеми: - Компонент **завантажує дані (data fetching)**, - **Відображає UI**, - **Містить бізнес-логіку** (видалення), - **Керує станом**. -> Занадто багато відповідальності в одному місці. -> Важко перевикористовувати, тестувати, підтримувати. --- ## Приклад з SRP (правильний підхід) Розділимо обов'язки: ### 1. Компонент відповідає за дані: ```javascript function useUser() { const [user, setUser] = useState(null); useEffect(() => { fetch('/api/user').then(res => res.json()).then(setUser); }, []); const deleteUser = async () => { await fetch(`/api/user/${user.id}`, { method: 'DELETE' }); setUser(null); }; return { user, deleteUser }; } ``` --- ### 2. Компонент відображає дані (UI): ```javascript function UserProfileView({ user, onDelete }) { if (!user) return <div>Loading...</div>; return ( <div> <h1>{user.name}</h1> <button onClick={onDelete}>Видалити користувача</button> </div> ); } ``` --- ### 3. Компонент-композиція (контейнер): ```javascript function UserProfile() { const { user, deleteUser } = useUser(); return <UserProfileView user={user} onDelete={deleteUser} />; } ``` Тепер: - `useUser` - відповідає **за дані і бізнес-логіку**; - `UserProfileView` - відповідає **тільки за UI**; - `UserProfile` - **збирає їх разом**. --- ## Переваги SRP у React | Перевага | Що дає | |---|---| | Зрозумілість | Кожен компонент робить щось одне і очевидне | | Перевикористовуваність | UI-компонент можна використовувати з іншими даними | | Тестованість | Можна окремо тестувати UI і логіку | | Підтримуваність | Зміна логіки не ламає розмітку | | Продуктивність | Простіше оптимізувати окремі частини | | Розширюваність | Можна додавати нові функції без правок старих компонентів | --- ## Типові категорії відповідальності в React | Категорія | Приклади компонентів | |---|---| | **Презентаційні (UI)** | кнопки, картки, форми, списки, layout | | **Контейнерні (логіка)** | завантаження даних, виклики API, обробка подій | | **Композиційні** | збирають UI-компоненти разом | | **Хуки / Логічні блоки** | містять бізнес-логіку без UI (`useAuth`, `useCart`, `useUser`) | --- ## Приклад архітектури за SRP ```javascript /components ├── ui/ │ ├── Button.tsx ← UI-компонент │ ├── Card.tsx ← UI-компонент │ └── UserProfileView.tsx← Відображення ├── containers/ │ └── UserProfile.tsx ← Контейнер /hooks └── useUser.ts ← Логіка даних ``` -> Кожен рівень робить **тільки свою справу**, React-компоненти стають як "чисті функції інтерфейсу". --- ## Коли SRP порушується найчастіше Типові ситуації: 1. Компонент завантажує дані і одразу їх рендерить; 2. UI-компонент зберігає локальний state, не пов'язаний з відображенням; 3. Один компонент керує і layout'ом, і логікою; 4. Надлишкові `useEffect` всередині UI-компонентів. --- ## Підсумок | Що означає SRP | У React це означає | |---|---| | "Одна відповідальність" | Компонент вирішує одну задачу | | Легко тестувати | Тому що робить щось одне | | Легко розширювати | Зміна логіки не ламає UI | | Архітектурно чисто | UI, логіка і дані - окремо | | Приклад | `useUser` (логіка) + `UserProfileView` (UI) + `UserProfile` (композиція) | --- **Простими словами:** > Компонент React повинен бути як чистий інструмент: > **одна мета, одна поведінка, одне місце, де щось може зламатися.**Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.