offline version v3
Запись на курсы по HTML, CSS, JavaScript, PHP, фреймворкам и CMS,
а также: помощь в поиске работы и заказов, стажировка на реальных проектах→
menu

Хук состояния useReducer в React

Хук useReducer работает со стейтами. Это своего рода альтернатива useState. Хук useReducer позволяет нам добавлять в компонент функцию, называемую редьюсер.

Редьюсер - это такой тип простых, чистых функций, которые принимают объект предыдущего стейта и объект действия и возвращают объект нового стейта.

В хуке useReducer эта функция работает подобно reducer в Redux, она возвращает тот или иной результат в зависимости от определенного типа действия.

Давайте перейдем к реализации. Для примера сделаем счетчик с двумя кнопками. По клику на одну значение счетчика будет увеличиваться, на другую уменьшаться.

Для начала импортируем функцию нашего хука useReducer:

import { useReducer } from 'react';

Давайте теперь в функции компонента App обозначим стейт count и функцию dispatch, которая будет обновлять стейт:

function App() { const [count, dispatch]; }

В хук useReducer нам нужно передать функцию reducer, которую мы напишем позже и начальное значение стейта count, пусть оно будет 10:

function App() { const [count, dispatch] = useReducer(reducer, 10); }

Давайте будем выводить count в абзац:

return ( <p>count: {count}</p> );

Теперь под абзацем добавим две кнопки. По клику на первую мы будем вызывать reducer, передавая ему тип действия increase, другими словами, по которому значение счетчика будет увеличиваться. По клику на вторую мы будем уменьшать значение счетчика, передавая в reducer тип действия decrease:

return ( <> <p>count: {count}</p> <button onClick={() => dispatch({ type: 'increase' })}>+</button> <button onClick={() => dispatch({ type: 'decrease' })}>-</button> </> );

И наконец, нам остается написать наш reducer, который будет вычислять и возвращать следующее значение стейта, в зависимости от действия, которое мы передали в функцию dispatch.

Давайте разместим функцию reducer сразу после строки импорта, но перед функцией компонента App. Функция reducer принимает параметрами наш стейт и объект action, у которого нас интересует свойство type:

function reducer(count, action) { switch (action.type) { } }

Оформим этот кусочек кода, придерживаясь соглашения в React, в виде конструкции switch-case. Если значение type было в increase, то значение стейта увеличится на 1, если decrease, то уменьшится на 1. По умолчанию reducer вернет неизмененный стейт.

function reducer(count, action) { switch (action.type) { case 'increase': return count + 1; case 'decrease': return count - 1; default: return count; } }

Соберем все вместе и получим следующий код:

import { useReducer } from 'react'; function reducer(count, action) { switch (action.type) { case 'increase': return count + 1; case 'decrease': return count - 1; default: return count; } } function App() { const [count, dispatch] = useReducer(reducer, 10); return ( <> <p>count: {count}</p> <button onClick={() => dispatch({ type: 'increase' })}>+</button> <button onClick={() => dispatch({ type: 'decrease' })}>-</button> </> ); } export default App;

Нужно отметить, что этот хук идеален для компонентов со сложной логикой обновления стейтов.

Пусть у вас на экране отображается какое-то слово (например 'React'). Заведите для этого соответствующий стейт с начальным значением. Пусть у вас будет две кнопки. По нажатию на первую в конец вашего слова каждый раз будет дописываться восклицательный знак, а на вторую - вопросительный. Для решения задачи используйте хук useReducer.