本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →
combineReducers(reducers)
概述
combineReducers 辅助函数将包含多个不同"切片 reducer"函数的对象,转换为可传递给 Redux Toolkit configureStore(或旧版 createStore 方法)的单一组合 reducer 函数。
生成的组合 reducer 会在每次 action 派发时调用所有切片 reducer,并将其结果收集到单一状态对象中。这使得我们可以将 reducer 逻辑拆分为独立函数,每个函数分别管理自己的状态切片。
通常你无需手动调用此方法——当你向 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 函数的对象,这些函数需要合并为一个 reducer。
combineReducers({
posts: postsReducer,
comments: commentsReducer
})
下方注意事项列出了每个传入 reducer 必须遵守的规则。
返回值
(函数):一个会调用 reducers 对象内所有 reducer 的函数,并构建具有相同结构的 state 对象。
注意事项
此函数带有轻度倾向性,主要帮助初学者避免常见陷阱。因此它会强制实施某些在手动编写根 reducer 时无需遵循的规则。
任何传递给 combineReducers 的 reducer 必须满足以下规则:
-
对于任何未识别的 action,必须返回接收到的第一个参数
state -
绝对不可返回
undefined。通过提前return语句很容易意外触发此情况,因此combineReducers会直接抛出错误而非让错误在其他地方显现 -
当接收到的
state为undefined时,必须返回该 reducer 的初始状态。根据前一条规则,初始状态也不得为undefined。使用可选参数语法指定很方便,但也可显式检查第一个参数是否为undefined
尽管 combineReducers 会尝试检查你的 reducer 是否符合部分规则,你仍需牢记这些规则并尽力遵守。combineReducers 将通过传递 undefined 来检查你的 reducer——即使你通过 Redux.createStore(combineReducers(...), initialState) 指定了初始状态也会执行此检查。因此,必须确保你的 reducer 在接收 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函数,其工作方式可能不同,甚至可以手动从子 reducer 组装状态对象,并显式编写根 reducer 函数,就像编写任何其他函数一样。 -
你可以在 reducer 层级的任何级别调用
combineReducers。它不一定非要在顶层使用。事实上,你可以再次使用它来将过于复杂的子 reducer 拆分为独立的孙 reducer,以此类推。