combineReducers(reducers)
概述
combineReducers
辅助函数将一个对象(其值为不同的“切片 reducer”函数)转换为一个单一的组合 reducer 函数,你可以将其传递给 Redux Toolkit 的 configureStore
(或传统的 createStore
方法)。
生成的组合 reducer 会在每次分发动作时调用每个切片 reducer,并将它们的结果收集到一个单一的 state 对象中。这使得能够将 reducer 逻辑拆分成独立的函数,每个函数独立管理自己的 state 切片。
这通常很少需要 - Redux Toolkit 的 configureStore
方法 会在您传入切片 reducer 对象时自动调用 combineReducers
const store = configureStore({
reducer: {
posts: postsReducer,
comments: commentsReducer
}
})
如果您需要先手动构建根 reducer,您仍然可以自己调用 combineReducers()
。
状态切片
由 combineReducers()
生成的状态将每个 reducer 的状态命名空间化,并在传递给 combineReducers()
的键下。
示例
rootReducer = combineReducers({potato: potatoReducer, tomato: tomatoReducer})
// This would produce the following state object
{
potato: {
// ... potatoes, and other state managed by the potatoReducer ...
},
tomato: {
// ... tomatoes, and other state managed by the tomatoReducer, maybe some nice sauce? ...
}
}
您可以通过在传递的对象中为 reducer 使用不同的键来控制状态键名。例如,您可以调用 combineReducers({ todos: myTodosReducer, counter: myCounterReducer })
使状态形状为 { todos, counter }
。
参数
reducers
(对象): 一个对象,其值对应于需要组合成一个的不同的 reducer 函数。
combineReducers({
posts: postsReducer,
comments: commentsReducer
})
请参阅下面的说明,了解每个传递的 reducer 必须遵循的一些规则。
返回值
(函数): 一个 reducer,它调用 reducers
对象中的每个 reducer,并构建一个具有相同形状的状态对象。
说明
此函数略带主观性,并且倾向于帮助初学者避免常见的陷阱。这就是为什么它试图强制执行一些规则,如果您手动编写根 reducer,则不必遵循这些规则。
传递给 combineReducers
的任何 reducer 都必须满足以下规则
对于任何未识别的操作,它必须返回作为第一个参数传递给它的
state
。它永远不能返回
undefined
。通过提前的return
语句很容易错误地做到这一点,因此combineReducers
会在您这样做时抛出异常,而不是让错误在其他地方显现。如果传递给它的
state
是undefined
,它必须返回此特定 reducer 的初始状态。根据前面的规则,初始状态也不能是undefined
。使用可选参数语法指定它很方便,但您也可以显式检查第一个参数是否为undefined
。
虽然 combineReducers
会尝试检查你的 reducers 是否符合某些规则,但你应该牢记这些规则,并尽力遵循它们。combineReducers
会通过向你的 reducers 传递 undefined
来检查它们;即使你为 Redux.createStore(combineReducers(...), initialState)
指定了初始状态,也会这样做。因此,你 **必须** 确保你的 reducers 在接收 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 '@reduxjs/toolkit'
import todos from './todos'
import counter from './counter'
export default combineReducers({
todos,
counter
})
App.js
import { configureStore } from '@reduxjs/toolkit'
import reducer from './reducers/index'
const store = configureStore({
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
,它 以不同的方式工作,或者甚至手动从子 reducers 组装状态对象,并显式地编写一个根 reducer 函数,就像编写任何其他函数一样。你可以在 reducer 层级的任何级别调用
combineReducers
。它不必发生在顶部。事实上,你可以再次使用它将变得过于复杂的子 reducers 分裂成独立的孙子 reducers,等等。