Spec-Zone.ru › Redux 3

combineReducers(reducers)

По мере усложнения приложения вам захочется разделить вашу функцию сведения на отдельные функции, каждая из которых управляет независимыми частями состояния.

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

Результирующий редьюсер вызывает каждый дочерний редьюсер и собирает их результаты в один объект состояния. Структура объекта состояния соответствует ключам переданного объекта reducers.

Следовательно, объект состояния будет выглядеть так:

{
  reducer1: ...
  reducer2: ...
}

Вы можете управлять именами ключей состояния, используя разные ключи для редьюсеров в переданном объекте. Например, вы можете вызвать combineReducers({ todos: myTodosReducer, counter: myCounterReducer }) для того, чтобы структура состояния была { todos, counter }.

Распространённая конвенция — именовать редьюсеры по тем частям состояния, за которые они отвечают, так что вы можете использовать сокращенную запись свойств ES6: combineReducers({ counter, todos }). Это эквивалентно записи combineReducers({ counter: counter, todos: todos }).

Примечание для пользователей Flux

Эта функция помогает организовать ваши редьюсеры для управления своими частями состояния, аналогично тому, как вы бы имели разные Flux хранилища для управления разными состояниями. В Redux есть только одно хранилище, но combineReducers помогает сохранить ту же логическую структуру разделения между редьюсерами.

Аргументы

  1. reducers (Объект): Объект, значениями которого являются различные функции сведения, которые необходимо объединить в одну. См. примечания ниже для некоторых правил, которым должен соответствовать каждый переданный редьюсер.

В предыдущей документации предлагалось использовать синтаксис ES6 import * as reducers для получения объекта редьюсеров. Это стало источником многочисленных путаниц, поэтому мы теперь рекомендуем экспортировать один редьюсер, полученный с помощью combineReducers() из reducers/index.js вместо этого. Пример приведён ниже.

Возвращаемое значение

(Функция): Редьюсер, который вызывает каждый редьюсер внутри объекта reducers, и строит объект состояния с той же структурой.

Примечания

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

Любой редьюсер, переданный в combineReducers, должен удовлетворять этим правилам:

  • Для любого нераспознанного действия он должен возвращать state, переданное ему в качестве первого аргумента.

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

  • Если state, переданное ему, является undefined, он должен возвращать начальное состояние для этого конкретного редьюсера. Согласно предыдущему правилу, начальное состояние также не должно быть undefined. Удобно указывать его с помощью синтаксиса ES6 необязательных аргументов, но вы также можете явно проверить первый аргумент на предмет того, является ли он undefined.

Хотя combineReducers пытается проверить, соответствуют ли ваши редьюсеры некоторым из этих правил, вам следует помнить о них и по возможности следовать им. combineReducers проверит ваши редьюсеры, передав undefined в них; это делается даже если вы укажете начальное состояние для Redux.createStore(combineReducers(...), initialState). Поэтому вы обязаны убедиться, что ваши редьюсеры работают должным образом при получении undefined в качестве состояния, даже если вы никогда не собираетесь передавать undefined в свой собственный код.

Пример

reducers/todos.js

export default function todos(state = [], action) {
  switch (action.type) {
    case 'ADD_TODO':
      return state.concat([action.text])
    default:
      return state
  }
}

reducers/counter.js

export default function counter(state = 0, action) {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1
    case 'DECREMENT':
      return state - 1
    default:
      return state
  }
}

reducers/index.js

import { combineReducers } from 'redux'
import todos from './todos'
import counter from './counter'

export default combineReducers({
  todos,
  counter
})

App.js

import { createStore } from 'redux'
import reducer from './reducers/index'

let store = createStore(reducer)
console.log(store.getState())
// {
//   counter: 0,
//   todos: []
// }

store.dispatch({
  type: 'ADD_TODO',
  text: 'Use Redux'
})
console.log(store.getState())
// {
//   counter: 0,
//   todos: [ 'Use Redux' ]
// }

Советы

  • Эта функция-помощник — просто удобство! Вы можете написать свой собственный combineReducers, который работает иначе, или даже собрать объект состояния из дочерних редьюсеров вручную и написать функцию корневого сведения явно, как вы бы написали любую другую функцию.

  • Вы можете вызвать combineReducers на любом уровне иерархии редьюсеров. Это не обязательно должно происходить в верхней части. На самом деле, вы можете использовать его снова, чтобы разбить дочерние редьюсеры, которые становятся слишком сложными, на независимых внуков и так далее.

© 2015–2017 Dan Abramov
Licensed under the MIT License.
http://redux.js.org/docs/api/combineReducers.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API