Три принципа

Redux может быть описан тремя фундаментальными принципами:

Единственный источник правды

Состояние всего вашего приложения сохранено в дереве объектов внутри одного хранилища.

Это облегчает создание универсальных приложений. Состояние на сервере может быть сериализировано и отправлено на клиент без дополнительных усилий. Это упрощает отладку приложения, когда мы имеем дело с единственным деревом состояния. Вы также можете сохранять состояние вашего приложения для ускорения процесса разработки. И с единственным деревом состояния вы получаете функциональность типа Undo/Redo из коробки.

console.log(store.getState());

{
  visibilityFilter: 'SHOW_ALL',
  todos: [{
    text: 'Consider using Redux',
    completed: true,
  }, {
    text: 'Keep all state in a single tree',
    completed: false
  }]
}

Состояние только для чтения

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

Это гарантирует, что представления или функции, реагирующие на события сети (network callbacks), никогда не изменят состояние напрямую. Поскольку все изменения централизованы и применяются последовательно в строгом порядке, поэтому нет необходимости следить за "гонкой состояний". Действия - это всего лишь простые объекты, поэтому они могут быть залогированы, сериализированы, сохранены и затем воспроизведены, для отладки или тестирования.

store.dispatch({
  type: 'COMPLETE_TODO',
  index: 1
});

store.dispatch({
  type: 'SET_VISIBILITY_FILTER',
  filter: 'SHOW_COMPLETED'
});

Мутации написаны, как простые функции

Для определения того, как дерево состояния будет трансформировано действиями, вы пишете чистые редьюсеры.

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

function visibilityFilter(state = 'SHOW_ALL', action) {
  switch (action.type) {
  case 'SET_VISIBILITY_FILTER':
    return action.filter;
  default:
    return state;
  }
}

function todos(state = [], action) {
  switch (action.type) {
  case 'ADD_TODO':
    return [...state, {
      text: action.text,
      completed: false
    }];
  case 'COMPLETE_TODO':
    return [
      ...state.slice(0, action.index),
      Object.assign({}, state[action.index], {
        completed: true
      }),
      ...state.slice(action.index + 1)
    ];
  default:
    return state;
  }
}

import { combineReducers, createStore } from 'redux';
let reducer = combineReducers({ visibilityFilter, todos });
let store = createStore(reducer);

Вот и все! Теперь вы знаете все о Redux.