Когда я начинал с React, у React был один способ управления состоянием: компоненты класса. Каждый раз, когда вам нужно было поднять или опустить состояние в вашем приложении React, вам часто приходилось реорганизовывать компоненты функций в компоненты класса, чтобы это стало возможным. Это могло вызвать очень сложный рефакторинг, потому что теперь вы передавали не только состояние, но и методы класса, которые обновляли это состояние. Эти методы также должны быть привязаны к правильной лексической области видимости, иначе наше приложение не будет работать правильно.

Вот почему Redux часто использовался в React Apps. Redux, будучи глобальной государственной библиотекой общего назначения, имел два основных преимущества. Во-первых, он предоставил централизованный объект состояния, называемый хранилищем, на который можно было подписаться всякий раз, когда изменения вступали в силу. Во-вторых, он был построен на основе архитектуры потока, архитектуры функционального стиля, которая обеспечивает однонаправленный поток управления состоянием.

Это упростило решение о том, как управлять состоянием приложения. Можно просто перенести все, что вы хотите, в глобальный магазин, а затем любая часть вашего приложения может подписаться на магазин и соответствующим образом обновиться.

К счастью, для нас команда React дала нам два составных крючка, которые позволяют нам управлять состоянием в наших приложениях React. Эти хуки гораздо проще объединить в любой компонент React или в их собственный собственный хук. Мы уже говорили о ловушке useState, но есть еще одна ловушка, которая позволяет нам обрабатывать более сложное управление состоянием. Это называется useReducer крючком.

Какая польза от Reducer Hook?

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

Это было реализовано через «отправку действий» в хранилище, и функция-редуктор будет выполнять эти действия и извлекать новое состояние из предыдущего состояния и действия. Хук useReducer работает таким же образом, он принимает функцию редуктора и начальное состояние и возвращает текущее состояние и «функцию диспетчеризации», которую мы можем использовать для запуска изменений состояния, например:

const App = () => {
   const [state, dispatch] = useReducer(reducerFunc, initialSate);
 
/*
* component implementation goes here
*/ 
 
}

Что такое функция редуктора?

При просмотре документации редюсер - это функция, которая принимает состояние и действие и возвращает новое состояние. Меня это сбивало с толку. Почему это «функция редуктора»? Что сокращалось? Потом кто-то показал мне это, и это запомнилось мне навсегда.

Одна из святой троицы массивных методов - это метод reduce. Метод reduce принимает такую ​​функцию и начальное значение:

const reduceFunction = (accumulator, currentValue) => newAccumulator
arr.reduce(reduceFunction, initialValue)

Это достаточно просто понять, для каждого элемента в массиве он будет передавать текущее значение аккумулятора и текущее значение в массиве. Затем в функции вы вернете новое производное значение аккумулятора на основе текущего значения массива.

Это должно звучать очень похоже на определение функции редуктора, требуемой для хука useReducer. Фактически, после нескольких настроек у нас есть именно это:

const reducerFunction = (state, action) => newState
useReducer(reduceFunction, initialValue)

Определения функций такие же. Единственная разница в том, что один используется в массиве значений, а другой используется в одном предыдущем состоянии для создания нового состояния.

Насчет действия. Что это должно быть? Технически вы можете передать любое значение в диспетчерскую функцию, и оно будет передано в функцию-редуктор как действие. Тем не менее, многие берут страницу из библиотеки Redux и передают объект «действие».

Объект действия - это просто объект со свойством type, которое описывает это действие, например: { type: "update-user" }. Затем функция-редуктор может использовать этот тип, чтобы узнать, как получить новое состояние. Опять же, это соглашение, и React совсем не требует его.

Фантастический пример хука useReducer в действии можно найти в документации по реакции. Я очень рекомендую вам это проверить.

Каковы преимущества useReducer против useState

Прежде всего, каждое сообщение в блоге, в котором сравнивается ловушка useState и ловушка useReducer, должно указывать на то, что ловушка useState реализована под ловушкой с помощью ловушки useReducer. Тем не менее, крючок useReducer имеет два преимущества перед крючком useState.

Во-первых, он допускает сложную оркестровку состояний. Я специально использую слово «оркестровка». UseState очень прост, и большую часть времени нам достаточно просто. Тем не менее, когда вы обнаруживаете, что обновляете более одного состояния одновременно, вам, вероятно, следует подумать об использовании ловушки useReducer.

Второе преимущество состоит в том, что хук useReducer позволяет вам объединить всю логику состояния вместе и часто позволяет использовать одну и ту же формулировку в ваших бизнес-требованиях, таких как «update-user», «logout», «reset» и т. Д. . Для чего-то столь же простого, как «выход из системы», может потребоваться обновление нескольких состояний. Этим намного проще управлять, если вся логика обновления состояния находится в одной функции.

У меня есть отличный пример того, как закончить в Codeandbox. Я использую редуктор для управления спрайтом Link, который ходит по странице. Выполнение чего-то столь же простого, как движение вверх, вниз, влево или вправо, может привести к одновременному выполнению нескольких действий. UseReducer значительно упрощает поддержку этой логики.

В конечном итоге выбор остается за разработчиком. React теперь имеет первоклассную поддержку для управления состоянием простым или сложным способом. Оба могут быть легко подняты или опущены в любую часть нашего дерева компонентов, которая нам нужна. В результате стало намного проще управлять приложением.