跳至主内容
非官方测试版翻译

本页面由 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 } 形状的状态。

参数

  1. reducers (对象):一个值对应不同 reducer 函数的对象,这些函数需要合并为一个 reducer。
combineReducers({
posts: postsReducer,
comments: commentsReducer
})

下方注意事项列出了每个传入 reducer 必须遵守的规则。

返回值

(函数):一个会调用 reducers 对象内所有 reducer 的函数,并构建具有相同结构的 state 对象。

注意事项

此函数带有轻度倾向性,主要帮助初学者避免常见陷阱。因此它会强制实施某些在手动编写根 reducer 时无需遵循的规则。

任何传递给 combineReducers 的 reducer 必须满足以下规则:

  • 对于任何未识别的 action,必须返回接收到的第一个参数 state

  • 绝对不可返回 undefined。通过提前 return 语句很容易意外触发此情况,因此 combineReducers 会直接抛出错误而非让错误在其他地方显现

  • 当接收到的 stateundefined 时,必须返回该 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,以此类推。