С Redux мы можем использовать его для хранения данных в центральном месте нашего приложения JavaScript. Он может работать самостоятельно, а также является популярным решением для управления состоянием приложений React в сочетании с React-Redux.

В этой статье мы рассмотрим, как создавать действия, которые можно отправлять в наш магазин с помощью Redux.

Создайте магазин с одним редуктором

Мы можем создать магазин с одним редуктором, создав функцию редуктора. Затем мы можем использовать функцию createStore Redux для создания хранилища из редуктора.

С магазином мы можем подписаться на него, чтобы получать последние значения, а также отправлять с ним действия для обновления состояния в магазине, передавая его редуктору.

Например, мы можем написать следующий код для создания магазина и выполнения некоторых действий:

import { createStore } from "redux";
function todosReducer(state = [], action) {
  switch (action.type) {
    case "ADD_TODO":
      return [...state, action.todo];
    case "REMOVE_TODO":
      return state.filter(todo => todo !== action.todo);
    default:
      return state;
  }
}
let store = createStore(todosReducer);
store.subscribe(() => console.log(store.getState()));
store.dispatch({ type: "ADD_TODO", todo: "eat" });
store.dispatch({ type: "ADD_TODO", todo: "drink" });
store.dispatch({ type: "REMOVE_TODO", todo: "eat" });

В приведенном выше коде мы создали todosReducer, чтобы получать отправленные действия, а затем манипулировать состоянием, как мы хотим.

У нас есть инструкция switch, чтобы проверить type действия и затем действовать соответствующим образом.

Действие type указано в объекте, который мы передали в метод dispatch.

Если тип действия - “ADD_TODO”, то мы вставляем элемент todo в объект, который есть в аргументе dispatch, в конец массива и распределяем все старые значения перед ним.

Если тип действия - “REMOVE_TODO”, мы возвращаем новый массив, исключающий элемент задачи с заданным текстом todo.

В противном случае мы возвращаем то, что у нас уже есть.

Затем мы используем метод createStore для создания хранилища, чтобы мы могли вызвать dispatch для передачи простых объектов для управления данными в хранилище.

Мы также можем subscribe к нему, а затем вызвать getState(), чтобы получить последние значения.

Обратите внимание, что мы всегда делаем копию state, а затем возвращаем с ней что-то новое. Это предотвращает случайные изменения и непреднамеренное изменение объектов.

Создать магазин с несколькими редукторами

В большинстве приложений мы хотим хранить более одного типа данных в нашем магазине. Мы можем сделать это, создав несколько редукторов, а затем использовать функцию combineReducer из Redux, чтобы объединить их в одно хранилище.

Для этого мы можем написать что-то вроде следующего кода:

import { createStore, combineReducers } from "redux";
function todosReducer(state = [], action) {
  switch (action.type) {
    case "ADD_TODO":
      return [...state, action.todo];
    case "REMOVE_TODO":
      return state.filter(todo => todo !== action.todo);
    default:
      return state;
  }
}
function countReducer(state = 0, action) {
  switch (action.type) {
    case "INCREMENT":
      return state + 1;
    case "DECREMENT":
      return state - 1;
    default:
      return state;
  }
}
let reducers = combineReducers({
  todos: todosReducer,
  count: countReducer
});
let store = createStore(reducers);
store.subscribe(() => console.log("todos", store.getState().todos));
store.subscribe(() => console.log("count", store.getState().count));
store.dispatch({ type: "ADD_TODO", todo: "eat" });
store.dispatch({ type: "ADD_TODO", todo: "drink" });
store.dispatch({ type: "REMOVE_TODO", todo: "eat" });
store.dispatch({ type: "INCREMENT" });
store.dispatch({ type: "DECREMENT" });

В приведенном выше коде у нас есть 2 редуктора - todoReducer и countReducer.

Мы объединили их в один, вызвав функцию Redux combineReducers с именем состояния в качестве имени свойства и функцией редуктора в качестве значения.

combineReducers объединяет все редукторы в один редуктор, поэтому мы можем передать его в createStore. Мы можем выбрать любое название штата, какое захотим.

Хранилище создается путем передачи большого редуктора, возвращаемого из combineReducers.

Затем в subscribe обратных вызовах мы можем использовать store.getState() для получения всех состояний. Затем мы можем получить задачи со свойством todos и состояние count с помощью свойства count.

В console.log s должно получиться что-то вроде:

todos ["eat"]
count 0
todos ["eat", "drink"]
count 0
todos ["drink"]
count 0
todos ["drink"]
count 1
todos ["drink"]
count 0

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

Метод dispatch вызывается так же, как и в примере с одним редуктором.

Мы по-прежнему передаем тип действия и полезную нагрузку, если она есть.

Поскольку dispatch работает одинаково, независимо от того, сколько редукторов у нас есть в магазине, мы должны убедиться, что никакие 2 действия не имеют одинакового имени.

Примечания

combineReducers в некоторых случаях вызывает ошибки, чтобы снизить вероятность их совершения.

Это вызовет ошибку, если функция-редуктор не вернет state, заданный ей в качестве первого аргумента, если действие не распознано.

Кроме того, он никогда не должен возвращать undefined. Это слишком просто сделать с помощью раннего return оператора. Следовательно, combineReducers выдаст ошибку, если мы сделаем это вместо того, чтобы позволить ошибке проявиться где-то еще.

Если ему присвоено state undefined, он должен вернуть начальное состояние для конкретного редуктора. Это означает, что начальное состояние не может быть undefined.

Мы можем указать начальное состояние в качестве аргумента по умолчанию для параметра state.

Redux проверит эти правила, когда мы будем писать код.

Заключение

Мы можем создать магазин из еще одной функции-редуктора. Единственная разница в том, что мы должны использовать combineReducers для объединения нескольких редукторов в один большой редуктор, чтобы передать его в createStore. Мы можем перейти к единственному редуктору прямо в createStore.

Затем мы можем использовать getState, чтобы получить последнее возвращенное состояние всех редукторов. Состояния доступны из getState(), и мы можем получить свойства из возвращенного объекта getState, чтобы получить эти состояния.

Действия по отправке одинаковы, независимо от того, сколько редукторов у нас в магазине.