Когда я начинал с 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 теперь имеет первоклассную поддержку для управления состоянием простым или сложным способом. Оба могут быть легко подняты или опущены в любую часть нашего дерева компонентов, которая нам нужна. В результате стало намного проще управлять приложением.