Redux修改状态值而不被要求?

zf9nrax1  于 2022-11-12  发布在  其他
关注(0)|答案(1)|浏览(188)

我正在使用redux来管理我的状态,我在reducer中的初始状态包含到个数组!第一个(games)是我想修改的,第二个(InitialGames)是我不想修改的初始状态!
问题是我只在第一个数组上做了更改!但是当我在逻辑后控制我的状态时!我看到两个数组都被更改了???这很混乱!
我将要讨论的案例是PLAYER_DEAD

我的减速器

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

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

export default (state = initialState, action) => {
 switch (action.type) {
   case RESET_GAME:
     state.games[action.payload.gameIndex] =
       state.InitialGames[action.payload.gameIndex];
     console.log(state);
     return state;
   case ADD_GAME:
     return {
       games: [...state.games, action.payload.game],
       InitialGames: [...state.games, action.payload.game],
     };
   case PUT_INFOS:
     return {
       gameInfos: action.gameInfos,
     };
   case PLAYER_DEAD:

     let newGames = state.games;
     let newInitialGames = state.InitialGames;

     console.log("Before Changings", newGames, newInitialGames);

     let newTeam = newGames[action.payload.indexGame].teams[
       action.payload.index
     ].players.splice(0, 1);

     console.log(
       "After changings",
       newGames,
       newInitialGames
     );
     return {games:newGames,InitialGames:newInitialGames};
 }
 return state;
};
x3naxklr

x3naxklr1#

之所以会发生这种情况,是因为您将相同的action.payload.game对象传递给了两个数组:

return {
  games: [...state.games, action.payload.game],
  //               same objects ---------^------v
  InitialGames: [...state.games, action.payload.game],
}

当你在PLAYER_DEAD的情况下访问.teams数组时,你访问的是gamesInitialGames共享的内存中的同一个数组,同样的情况也适用于该数组中的任何内容,包括.teams数组对象中的.players数组。因为你使用.splice()以一种不可变的方式更新数组,您最终会直接修改状态,从而修改gamesInitialGames引用的同一个.players数组。
您需要确保不会使用.splice()之类的方法在适当的位置修改状态。

const newGames = state.games.map((game, i) => i === action.payload.indexGame
  ? game.teams.map((team, j) => j === action.payload.index
    ? {...team, players: team.players.slice(1)} // note slice, not splice
    : team
  )
  : game
);

在上面的例子中,我们Map了数组,当indx与要更新的项匹配时更新项。当更新players数组时,我们使用.slice()从数组中删除第一个项。
编写不可变的代码并不总是那么容易,这就是为什么redux工具包内置了immer支持,当你使用createSlice() API这样的API时,它允许你编写代码,就像你一直在改变你的状态一样。

相关问题