You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React-Redux Reducer单元测试:正确返回值咨询

Redux Reducer返回值:对象还是数组?怎么解决你的测试不匹配问题?

嘿,我能理解你在写单元测试时碰到这个返回值不匹配的困惑——明明预期是简洁的{"isConnected": false},结果拿到了一个混合了数组键和对象属性的奇怪结构,这大概率是因为你的reducer状态结构前后不一致导致的。我来给你拆解清楚:

核心原则:Reducer返回值必须和初始状态结构一致

Redux里的reducer本质是纯函数,它接收当前状态(state)和动作(action),返回新的状态值。这个状态可以是对象、数组、字符串、数字任何类型,但有个硬规则:你返回的状态结构必须和你定义的初始状态结构完全匹配。

比如:

  • 如果初始状态是{ isConnected: false }(对象类型),那所有分支的返回值都得是同结构的对象;
  • 如果初始状态是[{ isConnected: true }](数组类型),那reducer就该始终返回数组。

你的问题根源:状态结构被意外混淆了

你实际收到的{"0": {"isConnected": true}, "isConnected": false},这说明你的reducer在某个分支里错误地把对象状态当成数组来处理了。比如可能不小心写了类似数组拼接的代码:

// 错误示例:把对象状态当成数组来拼接
return [...state, { isConnected: false }];

因为数组在JS里本质是带数字键的对象,这么写就会把原来的对象属性(isConnected)和数组的索引键("0")混在一起,就出现了你看到的奇怪结构。

正确的写法示例(针对你的预期)

既然你预期返回{"isConnected": false},说明你的初始状态应该是对象类型。那正确的reducer应该这样写:

// 初始状态是对象
const initialState = { isConnected: true };

const connectionReducer = (state = initialState, action) => {
  switch (action.type) {
    case 'DISCONNECT':
      // 用展开运算符复制旧状态,再覆盖需要更新的属性——遵循不可变性
      return { ...state, isConnected: false };
    case 'CONNECT':
      return { ...state, isConnected: true };
    // 别忘了default分支返回原状态
    default:
      return state;
  }
};

这样处理DISCONNECT动作时,返回的就是你预期的{ isConnected: false },单元测试就能匹配上了。

什么时候用数组类型的状态?

如果你的状态是一组同类型的数据(比如多个连接实例),那用数组才合理。比如初始状态是[{ id: 1, isConnected: true }, { id: 2, isConnected: false }],这时候reducer里就会用map、filter或者展开运算符来处理数组,返回新的数组状态。

总结一下:没有“必须返回对象或数组”的强制要求,关键是保持状态结构的一致性,并且始终遵守Redux的不可变性原则——永远不要直接修改原state,要返回新的状态副本。

内容的提问来源于stack exchange,提问作者Oak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:22:17