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“.