Skip to main content

combineReducers(reducers)

概述

¥Overview

combineReducers 辅助函数将值与 "切片 reducer" 函数不同的对象转换为单个组合的缩减器函数,你可以将其传递给 Redux Toolkit 的 configureStore (或旧版 createStore 方法)

¥The combineReducers helper function turns an object whose values are different "slice reducer" functions into a single combined reducer function you can pass to Redux Toolkit's configureStore (or the legacy createStore method)

每当调度操作时,生成的组合 reducer 都会调用每个切片 reducer,并将其结果收集到单个状态对象中。这使得能够将化简器逻辑拆分为单独的函数,每个函数独立地管理自己的状态切片。

¥The resulting combined reducer calls every slice reducer any time an action is dispatched, and gathers their results into a single state object. This enables splitting up reducer logic into separate functions, each managing their own slice of the state independently.

提示

这应该很少需要 - 如果你传入切片 reducer 的对象,Redux Toolkit 的 configureStore 方法 会自动为你调用 combineReducers

¥This should be rarely needed - Redux Toolkit's configureStore method will automatically call combineReducers for you if you pass in an object of slice reducers:

const store = configureStore({
reducer: {
posts: postsReducer,
comments: commentsReducer
}
})

如果你需要先手动构造根 reducer,你仍然可以自己调用 combineReducers()

¥You can still call combineReducers() yourself if you need to construct the root reducer manually first.

状态切片

¥State Slices

combineReducers() 命名空间生成的状态将每个 reducer 在其键下的状态传递给 combineReducers()

¥The state produced by combineReducers() namespaces the states of each reducer under their keys as passed to combineReducers()

示例:

¥Example:

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? ...
}
}

你可以通过对传递的对象中的化简器使用不同的键来控制状态键名称。例如,你可以调用 combineReducers({ todos: myTodosReducer, counter: myCounterReducer }) 来表示状态形状为 { todos, counter }

¥You can control state key names by using different keys for the reducers in the passed object. For example, you may call combineReducers({ todos: myTodosReducer, counter: myCounterReducer }) for the state shape to be { todos, counter }.

参数

¥Arguments

  1. reducers(对象):一种对象,其值对应于需要合并为一个的不同 reducer 函数。

    ¥reducers (Object): An object whose values correspond to different reducer functions that need to be combined into one.

combineReducers({
posts: postsReducer,
comments: commentsReducer
})

请参阅下面的注释,了解每个通过的 reducer 必须遵循的一些规则。

¥See the notes below for some rules every passed reducer must follow.

返回

¥Returns

(功能):一个 reducer,调用 reducers 对象内的每个 reducer,并构造一个具有相同形状的状态对象。

¥(Function): A reducer that invokes every reducer inside the reducers object, and constructs a state object with the same shape.

注意

¥Notes

这个功能有点有态度,偏向于帮助初学者避免常见的陷阱。这就是为什么它会尝试强制执行一些规则,如果你手动编写根 reducer,则不必遵循这些规则。

¥This function is mildly opinionated and is skewed towards helping beginners avoid common pitfalls. This is why it attempts to enforce some rules that you don't have to follow if you write the root reducer manually.

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

¥Any reducer passed to combineReducers must satisfy these rules:

  • 对于任何无法识别的操作,它必须返回作为第一个参数提供给它的 state

    ¥For any action that is not recognized, it must return the state given to it as the first argument.

  • 它绝不能返回 undefined。通过早期的 return 语句很容易错误地执行此操作,因此如果你这样做,则 combineReducers 会抛出异常,而不是让错误在其他地方显现出来。

    ¥It must never return undefined. It is too easy to do this by mistake via an early return statement, so combineReducers throws if you do that instead of letting the error manifest itself somewhere else.

  • 如果给它的 stateundefined,它必须返回该特定 reducer 的初始状态。根据前面的规则,初始状态也不能是 undefined。使用可选参数语法指定它很方便,但你也可以显式检查第一个参数是否为 undefined

    ¥If the state given to it is undefined, it must return the initial state for this specific reducer. According to the previous rule, the initial state must not be undefined either. It is handy to specify it with optional arguments syntax, but you can also explicitly check the first argument for being undefined.

combineReducers 尝试检查你的 reducer 是否符合其中一些规则时,你应该记住它们,并尽力遵循它们。combineReducers 将通过将 undefined 传递给你的 reducer 来检查它们;即使你将初始状态指定为 Redux.createStore(combineReducers(...), initialState),也会执行此操作。因此,你必须确保你的 reducer 在接收 undefined 作为状态时正常工作,即使你从未打算让它们在你自己的代码中实际接收 undefined

¥While combineReducers attempts to check that your reducers conform to some of these rules, you should remember them, and do your best to follow them. combineReducers will check your reducers by passing undefined to them; this is done even if you specify initial state to Redux.createStore(combineReducers(...), initialState). Therefore, you must ensure your reducers work properly when receiving undefined as state, even if you never intend for them to actually receive undefined in your own code.

示例

¥Example

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' ]
// }

提示

¥Tips

  • 这个助手只是一个方便!你可以编写自己的 combineReducers工作方式不同,甚至可以手动组装子 reducer 中的状态对象并显式编写根 reducer 函数,就像编写任何其他函数一样。

    ¥This helper is just a convenience! You can write your own combineReducers that works differently, or even assemble the state object from the child reducers manually and write a root reducer function explicitly, like you would write any other function.

  • 你可以在 reducer 层次结构的任何级别调用 combineReducers。它不一定发生在顶部。事实上,你可以再次使用它来将过于复杂的子 reducer 拆分为独立的孙子 reducer,依此类推。

    ¥You may call combineReducers at any level of the reducer hierarchy. It doesn't have to happen at the top. In fact you may use it again to split the child reducers that get too complicated into independent grandchildren, and so on.