Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «useReducer vs useState». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**`useReducer`** - це хук React, який дозволяє керувати станом через функцію-редюсер (reducer). Він схожий на принцип Redux: стан змінюється не напряму, а через "дію" (action). **Ключове:** `useState` просто зберігає значення, а `useReducer` керує складнішою логікою оновлення через `dispatch({ type, payload })`.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Що робить `useReducer` `useReducer` - це хук React, який дозволяє керувати станом **через функцію-редюсер (reducer)**. Він схожий на принцип Redux: > стан змінюється не напряму, а через "дію" (action). --- ### Синтаксис ```javascript const [state, dispatch] = useReducer(reducer, initialState); ``` - `state` - поточний стан - `dispatch` - функція, яка відправляє "дію" - `reducer(state, action)` - функція, яка отримує поточний стан і "дію", і **повертає новий стан** --- ### Простий приклад ```javascript function reducer(state, action) { switch (action.type) { case "increment": return { count: state.count + 1 }; case "decrement": return { count: state.count - 1 }; default: return state; } } function Counter() { const [state, dispatch] = useReducer(reducer, { count: 0 }); return ( <div> <p>{state.count}</p> <button onClick={() => dispatch({ type: "increment" })}>+</button> <button onClick={() => dispatch({ type: "decrement" })}>-</button> </div> ); } ``` Як це працює: 1. При кліку React викликає `dispatch({ type: "increment" })`. 2. React викликає `reducer(state, action)`. 3. Reducer повертає **новий стан** -> React перемальовує компонент. --- ## Чим `useReducer` відрізняється від `useState` | Критерій | `useState` | `useReducer` | |---|---|---| | Тип стану | Простий (одне значення) | Складний (об'єкт, масив, логіка оновлень) | | Оновлення | `setState(newValue)` | `dispatch({ type, payload })` | | Логіка оновлення | Прямо в компоненті | Винесена в окрему функцію (`reducer`) | | Коли використовувати | Прості кейси (лічильник, форма, перемикач) | Коли стан складний або залежить від різних дій | | Підходить для | Малих компонентів | Великих / складних станів | | Схоже на | Вбудована альтернатива Redux | Міні-Redux в одному компоненті | --- ## Приклад порівняння ### Варіант з `useState` ```javascript const [count, setCount] = useState(0); const increment = () => setCount(count + 1); const decrement = () => setCount(count - 1); ``` Просто, але погано масштабується, якщо логіка складна. --- ### Варіант з `useReducer` ```javascript function reducer(state, action) { switch (action.type) { case "increment": return { ...state, count: state.count + 1 }; case "decrement": return { ...state, count: state.count - 1 }; case "reset": return { ...state, count: 0 }; default: return state; } } const [state, dispatch] = useReducer(reducer, { count: 0 }); ``` Тепер ти можеш централізовано керувати логікою - зручно, коли багато розгалужень або станів. --- ## Коли краще використовувати `useReducer` Використовуй `useReducer`, коли: 1. Стан **складний** (наприклад, об'єкт з кількома полями). 2. Логіка оновлення **залежить від різних типів дій**. 3. Кілька частин коду можуть **оновлювати той самий стан**. 4. Хочеш **розділити логіку (reducer)** і **UI-компонент**. Приклади: - Форма з валідацією - Багатоетапний процес (wizard / onboarding) - Список елементів з фільтрацією, сортуванням, додаванням, видаленням --- ## Приклад "форма" на `useReducer` ```javascript function formReducer(state, action) { switch (action.type) { case "changeField": return { ...state, [action.field]: action.value }; case "reset": return { name: "", email: "" }; default: return state; } } function Form() { const [form, dispatch] = useReducer(formReducer, { name: "", email: "" }); return ( <form> <input value={form.name} onChange={(e) => dispatch({ type: "changeField", field: "name", value: e.target.value }) } /> <input value={form.email} onChange={(e) => dispatch({ type: "changeField", field: "email", value: e.target.value }) } /> <button onClick={() => dispatch({ type: "reset" })}>Clear</button> </form> ); } ``` Тепер можна легко розширювати форму - просто додаєш новий `case`. --- ## Підсумок | Питання | Відповідь | |---|---| | Що робить `useReducer`? | Керує станом через функцію-редюсер, реагуючи на "дії" (actions) | | Чим відрізняється від `useState`? | `useState` просто зберігає значення, `useReducer` керує складною логікою | | Коли використовувати? | При складних або пов'язаних оновленнях | | Коли не варто? | Для простих чисел, рядків, прапорців - простіше `useState` | | Чим схожий на Redux? | Той самий принцип "action -> reducer -> new state", тільки локально |Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.