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

Redux中仅修改games数组却导致InitialGames数组被意外修改

问题原因及修复方案

核心问题:引用类型特性与Redux纯函数原则违反

你遇到的问题本质是JavaScript引用类型的特性,加上违反了Redux reducer的纯函数要求:

  • ADD_GAME中,games和InitialGames存入的是同一个action.payload.game对象的引用,并非独立副本,修改其中一个数组内的对象属性时,另一个数组里的对应对象会同步变化。
  • PLAYER_DEAD里let newGames = state.games只是赋值原数组的引用,没有创建新数组,后续splice操作直接修改了原数组内容,同时因为InitialGames里的游戏对象与games里的是同一引用,导致InitialGames也被改动。
  • RESET_GAME直接修改原state.games,违反了Redux reducer不能直接修改原状态的规则。
  • PUT_INFOS返回状态时未保留原有games和InitialGames,会导致状态丢失。

修复步骤

  1. 深拷贝游戏对象:让games和InitialGames存储完全独立的对象副本,切断引用关联。
  2. 操作前创建新数组/对象:所有状态修改都基于拷贝后的新对象进行,避免直接修改原状态。
  3. 保留原有状态属性:返回新状态时,通过扩展运算符保留未修改的状态字段。

修复后的Reducer代码

import { ADD_GAME, PLAYER_DEAD, PUT_INFOS, RESET_GAME } from "./actions";

const initialState = {
  games: [],
  InitialGames: [],
};

// 深拷贝游戏对象(若对象含JSON无法序列化的内容,可改用lodash.cloneDeep)
const deepCloneGame = (game) => JSON.parse(JSON.stringify(game));

export default (state = initialState, action) => {
  switch (action.type) {
    case RESET_GAME:
      const clonedInitialGame = deepCloneGame(state.InitialGames[action.payload.gameIndex]);
      return {
        ...state,
        games: state.games.map((game, index) => 
          index === action.payload.gameIndex ? clonedInitialGame : game
        )
      };

    case ADD_GAME:
      const clonedGame = deepCloneGame(action.payload.game);
      return {
        ...state,
        games: [...state.games, clonedGame],
        InitialGames: [...state.InitialGames, clonedGame],
      };

    case PUT_INFOS:
      return {
        ...state,
        gameInfos: action.gameInfos,
      };

    case PLAYER_DEAD:
      // 深拷贝整个games数组,确保不影响原状态和InitialGames
      const newGames = state.games.map(game => deepCloneGame(game));
      newGames[action.payload.indexGame].teams[action.payload.index].players.splice(0, 1);
      return {
        ...state,
        games: newGames
      };

    default:
      return state;
  }
};

补充说明

如果游戏对象层级复杂(包含函数、Symbol等),可以使用lodash.cloneDeep实现深拷贝,需先安装lodash依赖。始终遵守Redux核心规则:reducer必须是纯函数,禁止直接修改原状态,必须返回新状态对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 06:06:25