Хук UseReducer в React с подробным объяснением
Изучение React может быть нелегким делом, я это понимаю, и все, кто в конечном итоге прочитает эту статью, тоже, но я стремлюсь упростить эти сложные компоненты в React. Одна вещь, которая очень характерна для React, - это работа с состояниями. Для обновления пользовательского интерфейса и работы с состояниями используется хук useState
. Хук useState
очень прост в освоении, его можно выучить за 2-3 минуты, но когда вы начинаете работать над более сложными веб-сайтами, вы начинаете видеть ограничения хука useState
React. Это похоже на то, как маленькие ложки или чашки используются для младенцев, но когда ребенок становится старше, он понимает, насколько ограничены эти чашки или ложки, и тянется за большей ложкой. Надеюсь, эта аналогия понятна.
UseReducer() 101: Для чего нужен этот хук?
Хук useReducer()
- это хук React, который используется для управления сложными состояниями. И да, этот useReducer
точно такой же, как useState
для управления состоянием, но с некоторыми отличиями, о которых мы поговорим в этой статье. Одна важная вещь, которую следует отметить в отношении хука useReducer
, - это то, что вы можете отслеживать несколько частей состояния с помощью более сложной структуры данных, такой как массив или объект. Прочитав эту статью, вы не только поймете, что такое useReducer
, но и будете знать, когда правильно его использовать.
Синтаксис UseReducer
const [state, dispatch] = useReducer(reducer, initialState);
Это синтаксис для хука useReducer
, который очень похож на синтаксис useState
, приведённый ниже:
const [value, setValue] = useState(0)
В обоих синтаксисах мы получаем объект state
и функцию для работы с этим состоянием, но useState
принимает один аргумент, а useReducer
- от двух до трех аргументов, и это одно из отличий.
Первый аргумент, который принимает useReducer
, - это функция reducer
. Это функция, которая принимает в качестве параметров состояние и объект действия. В зависимости от объекта действия функция reducer
должна обновить состояние неизменяемым образом и вернуть новое состояние.
Вторым аргументом является начальное состояние. Начальное состояние - это значение, которым инициализируется состояние, которое является обязательным и возвращает ошибку, если оно не будет определено.
Как начать использовать хук UseReducer?
Чтобы начать использовать хук useReducer
, первое, что вам нужно сделать, это импортировать хук из React следующим образом:
import { useReducer } from 'react';
После импорта хука useReducer
вы можете приступить к его использованию в своём коде. Давайте посмотрим, как мы можем начать использовать useReducer
в нашем коде.
Создание счётчика с помощью useReducer
В этой статье мы будем создавать счетчик с помощью хука useReducer
, а позже посмотрим, как это сделать с помощью useState
.
Шаг 1: Импортируйте хук useReducer
из React
import { useReducer } from 'react';
Шаг 2: Определите, с чем именно предстоит работать
import { useReducer } from 'react';
const initialState = {
count : 0
};
export default function Demo () {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
<h1>I am a counter</h2>
<button>+</buuton>
<p>{count}</p>
<button>-</buuton>
</div>
)
}
В приведенном выше блоке кода я определил множество вещей, и далее мы будем работать над функциональностью. Первое, что мы сделаем, это напишем функцию reducer
. Именно в функции reducer
будет написана большая часть функциональности. Функция reducer
, как я уже говорил, принимает в качестве аргумента копию состояния и действия. Затем, в зависимости от типа действия, она собирается внести некоторые изменения в эту копию состояния и вернуть состояние, так что давайте вернемся к коду.
function reducer(state, action) {
switch (action.type) {
default:
throw new Error('action unknown');
}
}
В функции reducer
мы будем использовать переключатель для определения новых случаев. В action.type
содержится имя операции, которую нужно выполнить. Это строка, и вы можете задать любое значение. Только убедитесь, что оно имеет отношение к выполняемому действию, чтобы было удобнее читать. Если тип действия в диспетчере не соответствует ни одному из действий, он выдаст ошибку, так что это важная часть кода. Давайте перейдем к написанию функциональности для увеличения состояния.
function reducer(state, action) {
switch (action.type) {
case 'increment' :
return {
...state, count: state.counter + 1;
}
case 'decrement' :
return {
...state, count: state.counter - 1;
}
default:
throw new Error('action unknown');
}
}
Определив случай, вы возвращаете состояние обратно и пишете нужную вам функциональность, всё очень просто. Если вам интересно, как мы заставим кнопки работать, то я вас понимаю.
import { useReducer } from 'react';
const initialState = {
count : 0
};
function reducer(state, action) {
switch (action.type) {
case 'increment' :
return {
...state, count: state.counter + 1;
}
case 'decrement' :
return {
...state, count: state.counter - 1;
}
default:
throw new Error('action unknown');
}
}
export default function Demo () {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
<h1>I am a counter</h2>
<button onClick={() => dispatch({ type: 'increment' })} >+
</button>
<p>{count}</p>
<button onClick={() => dispatch({ type: 'decrement' })} >-
</button>
</div>
)
}
Обработчики событий нажатия кнопок используют функцию dispatch()
для отправки соответствующего объекта действия, и вот как просто использовать UseReducer
в вашем коде, правда? Для сравнения давайте напишем тот же код с использованием React-хука useState
.
Построение счётчика с использованием useStateBuiding и useState
import { useState } from 'react';
export default function Demo () {
const [count, setCount] = useState(0);
function increase () {
setCount(count + 1)
}
function decrease () {
setCount(count - 1)
}
return (
<div>
<h1>I am a counter</h2>
<button onClick={increase} >+</button>
<p>{count}</p>
<button onClick={decrease} >-</button>
</div>
)
}
Вот как выглядит счётчик при написании его с помощью React-хука useState
. Я знаю, что это всё ещё выглядит просто, но представьте, что у вас есть 5 состояний, которые зависят друг от друга - вам придется постоянно писать разные состояния и функции, в отличие от хука useReducer
, где вы можете определить всё в функции reducer
.
Как узнать, когда использовать React-хуки UseState и UseReducer?
Предпочтите useState
, если:
- Примитивы JavaScript (строка, булево число, число) в качестве состояния (например, наш первый пример использования).
- Управляемое состояние - простая бизнес-логика.
- Есть различные свойства, которые не изменяются коррелированно и могут управляться несколькими хуками
useState
.
Предпочтите UseReducer
, если:
- Объекты или массивы JavaScript в качестве состояния (например, наш второй пример использования).
- Различные свойства, связанные между собой, которые должны управляться одним объектом состояния.
Заключение
Надеюсь, эта статья была достаточно полезной для вас и помогла понять основы хука useReducer
. Я хочу, чтобы вы бросили себе вызов и попробовали реализовать хук useReducer
в своем следующем проекте React, а не полагались только на useState
. Я хотел бы услышать ваши отзывы в разделе комментариев!