Хук состояния 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.