Redux-приложение это:
- состояние (state) приложения в одном месте;
- однонаправленный поток данных;
Все состояние вашего приложения сохранено в объекте внутри одного хранилища (store). Единственный способ изменить дерево состояния - это вызвать действие (action), объект описывающий то, что случилось. Чтобы указать, каким образом действия преобразовывают дерево состояния - нужно использовать чистые "редюсеры".
ACTIONS Действия - это структуры, которые передают данные из вашего приложения в хранилище. Они являются единственными источниками информации для хранилища. Действия отправляются в хранилище используя метод store.dispatch(). Лучшая практика - это передавать как можно меньше данных в каждом действии. Например, лучше отправить index объекта, чем весь объект.
// Единственный способ изменить внутреннее состояние - это вызвать действие // Действия могут быть сериализированы, залогированы или сохранены и далее // воспроизведены. Примеры: store.dispatch({ type: 'INCREMENT' }); store.dispatch({ type: 'ADD_ITEM', index: 5 });
Обычно тип действия, описывают как константу. Например: const GET_PHOTO_REQUEST = 'GET_PHOTO_REQUEST' const GET_PHOTO_SUCCESS = 'GET_PHOTO_SUCCESS'
Чтобы вызвать actions, мы должны написать функцию, которая в рамках Flux/Redux называется - ActionsCreator. Генераторы действий (action creators) просто возвращают action: function addTodo(text) { return { type: ADD_TODO, text } }
Синхронное действие (actions):
- пользователь кликнул на кнопку
- dispatch action {type: ТИП_ДЕЙСТВИЯ, payload: доп.данные}
- интерфейс обновился
Асинхронное действие:
- пользователь кликнул на кнопку
- dispatch action {type: ТИП_ДЕЙСТВИЯ_ЗАПРОС}
- запрос выполнился успешно
- dispatch action {type: ТИП_ДЕЙСТВИЯ_УСПЕШНО, payload: доп.данные}
- запрос выполнился неудачно
- dispatch action {type: ТИП_ДЕЙСТВИЯ_НЕУДАЧНО, error: true, payload: доп.данные ошибки}
REDUCER Редюсер - это чистая функция, которая принимает предыдущее состояние и действие (state и action) и возвращает следующее состояние (новую версию предыдущего). Работа Reducer'а - среагировать на вызов Action и изменить состояние приложения. Формат состояния (state) зависит от вас: он может быть примитивом, массивом, объектом или даже структурой данных Immutable.js. Важно только одно: нельзя изменять объект состояния напрямую, вместо этого, стои возвращать новый объект, если состояние изменилось.
function counter(state = 0, action) { switch (action.type) { case 'INCREMENT': return state + 1 case 'DECREMENT': return state - 1 default: return state } }
Вот список того, чего никогда нельзя делать в редюсере:
- Непосредственно изменять то, что пришло в аргументах функции;
- Выполнять какие-либо сайд-эффекты: обращаться к API или осуществлять переход по роутам;
- Вызывать не чистые функции, например Date.now() или Math.random().
Главный редьюсер можно разбить на несколько более мелких, и с помощью combineReducers из пакета redux собрать их воедино. Каждый мелкий редьюсер будет отвечать за некий срез состояния.
STORE Store, "объединяет" редьюсер (reducer) и действия (actions), а так же имеет несколько чрезвычайно полезных методов, например:
- содержит состояние приложения (application state);
- предоставляет доступ к состоянию с помощью getState();
- предоставляет возможность обновления состояния с помощью dispatch(action);
- регистрирует слушатели (listeners) c помощью subscribe(listener).
// Создаем хранилище. import { createStore } from 'redux'; import todoApp from './reducers'; let store = createStore(todoApp);
// Каждый раз при обновлении состояния - выводим его // Отметим, что subscribe() возвращает функцию для отмены регистрации слушателя let unsubscribe = store.subscribe(() => console.log(store.getState()); )
// Отправим несколько действий store.dispatch(addTodo('Learn about actions')); store.dispatch(addTodo('Learn about reducers')); store.dispatch(toggleTodo(0)); store.dispatch(toggleTodo(1));
// Прекратим слушать обновление состояния unsubscribe();
В отличии от Flux, в Redux только один объект Store.
ПОТОК ДАННЫХ (Data Flow) Жизненный цикл данных в любом Redux приложении включает в себя 4 шага:
- Вызов store.dispatch(action);
- Хранилище Redux вызывает функцию-редюсер, который ему передали. Хранилище передаст два аргумента при вызове редюсера: текущее дерево состояния (current state tree) и действие (action).
- Главный редюсер может комбинировать результат работы нескольких редюсеров в единственное дерево состояния приложения.
- Хранилище Redux сохраняет полное дерево состояния, которое возвращает главный редюсер. Это новое дерево является следующим состоянием приложения.
ИСПОЛЬЗОВАНИЕ С REACT Компоненты-контейнеры. Компоненты-контейнеры - это React-компоненты, задача которых общаться с Redux и связывать props и dispatch функции. Чтобы связать все компоненты-контейнеры с хранилищем нужно использовать , и передавать хранилище - только в Провайдер.
MIDDLEWARE Middleware принимают входные данные, добавляют что-то и передают данные дальше. Redux мидлвэры используют для логирования, сообщения об ошибках, общения с асинхронным API, роутинга и т.д.