Добро пожаловать в мою первую из серии статей об изучении Redux.
Что такое Redux?
Redux — это инструмент управления состоянием, который позволяет нам получать доступ и изменять состояние в нашем приложении без необходимости передавать его компонентам в качестве свойств. По мере роста наших приложений деревья наших компонентов могут стать очень глубокими, и передача части состояния в качестве свойств через несколько компонентов может стать очень сложной для обслуживания и отладки. Redux создает глобальное состояние (называемое «хранилищем»), к которому можно легко получить доступ на протяжении всего проекта. Это дает нам возможность использовать единственный источник достоверной информации. Кроме того, мы можем обновлять данные в магазине с помощью действий отправки.
Как получить доступ к состоянию?
Мы обернем наш проект Provider
react-redux
, что сделает наш магазин доступным во всем приложении. Затем мы сможем использовать функции Redux для отображения состояния в качестве свойств в компонентах, которые можно прочитать, как если бы они получали их от родительского компонента.
Как мы будем обновлять состояние?
Чтобы обновить наш state
или любую его часть, мы отправим действие, которое будет определено нами. действие – это простой объект JavaScript с атрибутом .type
. type
должна быть описательной строкой, например “count/incrementBy1,”
“ingredients/boilPotato,”
или “users/addNewUser.”
Первая часть — это функция или категория, к которой принадлежит действие, а вторая часть — то, что мы хотим сделать.
const incrementBy1Action = { type: 'count/incrementBy1' }
Куда мы отправляем действие для обновления состояния?
Мы отправляем наши действия в редьюсер. Это функция, которая получает два аргумента: наш текущий state
и объект action. Он будет использовать switch case
, if else
или loops
для обновления state
так, как этого хочет наше действие, и вернет новый state
:
counterReducer(state, action) => newState
Редукторы должны следовать некоторым правилам:
- Они должны вычислять только новое значение
state
на основе аргументовstate
и action. - Им не разрешено изменять существующий
state
. Обычно мы будем использовать оператор спреда(…state)
, чтобы скопировать существующийstate
, а затем внести необходимые изменения, возвращая новыйstate
. - Они не должны выполнять асинхронную логику, вычислять случайные значения или вызывать другие «побочные эффекты» (редукторы — это чистые функции).
Вот пример простого редьюсера, который может увеличить наше count
на 1:
function counterReducer( state = {count: 0}, action ) { if (action.type === 'count/incrementBy1') { return { ...state, count: state.count + 1 } } return state }
Итак, мы передаем state
и действие в наш редьюсер (обратите внимание, что мы установили значение счетчика состояния по умолчанию/начальное значение 0). Редуктор использует оператор if
, чтобы узнать, требует ли наше действие увеличения на 1. Если это так, он возвращает существующий state
с state.count
, увеличенным на 1. Если действие, которое мы передали, не увеличивалось на 1, оно просто возвращает state
как есть. Здесь мы можем добавить больше возможных действий и использовать switch case
вместо серии операторов if
.
Теперь, когда у нас есть понимание того, как работает редьюсер, давайте еще раз вернемся в наш магазин. Помните, что store — это объект, в котором живет state
нашего приложения. С нашим App
, обернутым в <Provider />
, он доступен во всем приложении. Но как он создается? store создается путем передачи reducer. Давайте использовать тот, который мы только что построили в качестве примера:
import { configureStore } from '@reduxjs/toolkit' const store = configureStore({ reducer: counterReducer })
Теперь у store
есть метод getState
, который возвращает текущее значение state
.
У store
также есть метод под названием dispatch
. Чтобы обновить state
и сохранить изменения, мы вызовем store.dispatch()
и передаем объект action. store запускает функцию reducer, обновляя новое значение, а затем мы можем вызвать store.getState()
, чтобы получить обновленное значение:
console.log(store.getState()) // { count : 0 } store.dispatch({ type: 'count/incrementBy1' }) console.log(store.getState()) // { count : 1 }
Обобщить:
- Мы создаем store с помощью функции reducer. После создания store вызывает reducer и сохраняет возвращаемое значение как исходное
state
. - Когда в приложении что-то происходит, например, когда пользователь нажимает кнопку увеличения, наш код отправляет действие в магазин, например
store.dispatch({ type: 'count/incrementBy1' })
- store снова запускает reducer, используя в качестве аргументов предыдущее
state
и текущее действие, а затем присваивает возвращаемое значение как новоеstate
. - Затем хранилище уведомляет все части пользовательского интерфейса, которые к нему подключены, об обновлении
state
, вызывая повторную визуализацию каждого из этих компонентов с использованием новых данныхstate
.
Надеюсь, это даст вам общее представление о потоке информации в Redux. Оставайтесь с нами, чтобы узнать больше о Redux и его использовании в наших проектах, и, пожалуйста, обращайтесь, если у вас есть какие-либо комментарии, советы или вопросы!