Добро пожаловать в мою первую из серии статей об изучении 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 и его использовании в наших проектах, и, пожалуйста, обращайтесь, если у вас есть какие-либо комментарии, советы или вопросы!