Redux е много популярна библиотека за управление на състоянието. Той опростява оригиналната архитектура на Flux, като комбинира всички магазини и диспечера в един обект на магазин.

Redux насърчава използването на функционално програмиране за управление на състоянието. Той въвежда концепцията за редукторната функция.

Редуктор

Редукторът е чиста функция, която приема състояние и действие като параметри и връща новото състояние.

Може да има много редуктори, управляващи части от основното състояние. Можем да ги комбинираме заедно с помощната функция combineReducers() и да създадем root редуктора.

Ето как може да изглежда редукторът todos:

import matchesProperty from "lodash/matchesProperty";
function todos(todos = [], action) {
 switch (action.type) {
  case "add_todo":
    const id = getMaxId(todos) + 1;
    const newTodo = { ...action.todo, id };
    return todos.concat([newTodo]);
  case "remove_todo":
    const index = todos.findIndex(matchesProperty("id",
                                  action.todo.id));
    return [...todos.slice(0, index), ...todos.slice(index + 1)];
  case "reset_todos":
    return action.todos;
  default:
    return state;
  }
}
export default todos;

state в този случай е списъкът със задачи. Можем да приложим към неговите действия като add_todo, remove_todo, reset_todos.

Редуктор по конвенция

Бих искал да се отърва от оператора switch в редуктора. Функциите трябва да са малки и да правят едно нещо.

Нека разделим редуктора на малки чисти функции с имена, съответстващи на типовете действия. Ще наричам тези сетерни функции. Всеки от тях приема състояние и действие като параметри и връща новото състояние.

function remove_todo(todos, action) {
  const index = todos.findIndex(matchesProperty("id",
                                action.todo.id));
  return [...todos.slice(0, index), ...todos.slice(index + 1)];
}
function reset_todos(todos, action) {
  return action.todos;
}
function add_todo(todos, action) {
  const id = getMaxId(todos) + 1;
  const newTodo = { ...action.todo, id};
  return todos.concat([newTodo]);
}

редуцирани действия

Бих искал да комбинирам всички тези малки функции заедно, за да създам оригиналната редуцираща функция. Можем да използваме помощната функция handleActions() от redux-actions за това.

import { handleActions } from "redux-actions";
const reducer = handleActions(
  { remove_todo, reset_todos, add_todo },
  []
);
export default reducer;

Функциите за настройка ще се изпълняват по конвенция. Когато влезе действие с тип remove_todo, ще се изпълни функцията за настройка remove_todo().

редуц-точки

На този етап бих искал да създам типове действия въз основа на имената на функциите за настройка. Ето как може да изглежда обектът с всички типове действия:

{
  remove_todo : "remove_todo",
  reset_todos: "reset_todos",
  add_todo: "add_todo"
}

Бих искал да използвам помощна функция, за да създам както редуктора, така и типа действие. Ето как може да изглежда кодът:

const { reducer, actionTypes } = createReducerAndActionTypes(
  { remove_todo, reset_todos, add_todo },
  []
);
export default reducer;
export { actionTypes };

redux-points е микро npm библиотека, създадена за тази цел. Ето наличните функции:

createReducer(): създава редуктора, като взема обект с всички сетер функции и първоначалното състояние.

createActionTypes(): създава типове действия, като взема обект с всички функции за настройка.

createReducerAndActionTypes(): създава както редуктора, така и типовете действия по конвенция. Той приема всички функции на настройка и първоначалното състояние.

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

import { actionTypes } from "../store/todos";
const { reset_todos, remove_todo, add_todo } = actionTypes;
function resetTodos(todos) {
  return {
    type: reset_todos,
    todos
  };
}
function addTodo(todo) {
  return {
    type: add_todo,
    todo
  };
}
function removeTodo(todo) {
  return {
    type: remove_todo,
    todo
  };
}
export { resetTodos, addTodo, removeTodo };

Заключение

Редукторът е чиста функция, която приема състояние и действие и връща новото състояние.

Функцията редуктор може да бъде създадена по конвенция. redux-actions може да се използва за тази цел.

Опитайте npm пакета redux-points, за да разделите редуктора на малки чисти функции с имена, съответстващи на типовете действия. Комбинирайте малките чисти функции, за да създадете оригиналния редуктор и свързаните типове действия.

„Ето примерния код на codesandbox“.