【问题标题】:What is the difference between these two Redux reducer cases?这两个 Redux reducer 案例有什么区别?
【发布时间】:2026-01-06 14:20:03
【问题描述】:

我看到有人为reducer写了这段代码:

export default function reducer(state, action) {
    switch(action.type) {
        case 'ADD_TODO':
            Object.assign({}, state, {
                todos: [{
                    text: action.text,
                    completed: false,
                }, ...state.todos]
            })
        default:
            return state;
    }
}

为什么不这样做呢?

case 'ADD_TODO':
   return [{text: action.txt, completed: false}, ...state.todos]

有什么区别?

【问题讨论】:

  • Object.assign 不是“很新”。它现在实际上已经“相当老”了。您定位的浏览器“非常旧”。

标签: javascript reactjs ecmascript-6 redux


【解决方案1】:

在 Redux 中,有一个 Splitting Reducers 的概念,用于在推断新状态时更好地组织。当你将一个reducer 拆分成多个不同的reducer,然后将它们与combineReducers 组合在一起时,实际上你给每个reducer 一个状态片 对应于它管理的各个状态。例如,我可以创建一个 todo 减速器来只管理每个待办事项,并且只知道待办事项内部的状态,而不是别的。

在您发布的第一个 sn-p 中,reducer 是某种“主”reducer。该示例中的reducer 函数是处理状态中的所有内容 的reducer,而不仅仅是待办事项,并且知道状态中的所有内容。这就是您需要此代码的原因:

Object.assign({}, state, {
    todos: [{
        text: action.text,
        completed: false,
    }, ...state.todos]
})

这会创建state 的副本以防止突变(通过Object.assign),然后使用新的待办事项更新克隆的statetodos 属性。在这个“主”reducer 中,reducer 管理所有状态,因此必须克隆状态并更新todo 属性。

在第二个示例中,它不会在同一个 reducer 中工作。那是因为您只返回一个数组作为新状态。这意味着,无论何时添加待办事项,state 都会变成一个数组。不好!您的第二个 sn-p 仅在您 将主减速器拆分为多个时才有效,并且您有一个单独的减速器只管理待办事项。这意味着,该 todo reducer 只会获得其各自的“状态片”。它只会知道 state 中的 todos 属性,而不会知道 state 中的其他内容:

export default function todos(state, action) { //This reducer is only aware of todos in state, nothing else.
  switch(action.type) {
    case 'ADD_TODO':
      return [{text: action.txt, completed: false}, ...state.todos] //This will modify only the `todos` property of state, not the whole state
  }
}

在你的主减速器文件中:

import todos from './your/todo/reducer/file';

combineReducers({
  todos
});

这里,todosstate 参数只会接收状态中的 todos 属性,它是切片。没有其他的。第一个 sn-p 将接收整个状态对象作为 state 参数。

【讨论】:

  • 编辑了问题,现在怎么样?
  • @MadelineRies 我添加了深入的解释,希望对您有所帮助。
最近更新 更多