即使设置了唯一键,也会对redux重复键做出反应

时间:2019-01-25 13:09:06

标签: javascript reactjs redux react-redux

我有一个包含6个对象的数组,这些对象具有一个uid和其他所有内容。这样一来,我可以重复它们并拥有一些占位符内容,直到准备好将对象添加到数组中为止。选择新对象时,我会设置一个唯一键。但是,即使我设置了唯一键,如果我两次选择相同的对象。似乎更新了重复项上的唯一键(即使唯一键不同)。

在这里查看运行中的代码/应用可能会更容易,问题的一个示例是先单击squirtle然后进行blastoise,然后注意显示的uid。然后再次单击squirtle,由于某种原因,它将用新的squirtles uid更新旧的squirtle,从而导致重复的键错误。 https://codesandbox.io/s/l75m9z1xwq或查看下面的代码。在我可以正常工作之前,Math.random只是占位符。

const initState = {
 party: [
 { uid: 0 },
 { uid: 1 },
 { uid: 2 },
 { uid: 3 },
 { uid: 4 },
 { uid: 5 }
 ]
};

当我单击某些东西时会触发该事件:

handleClick = pokemon => {
   // setup a uid, will need a better method than math.random later
   pokemon.uid = Math.random();

   this.props.addToParty(pokemon);
};

然后调用一个调度程序,该调度程序将触发以下减速器。实际上,这实际上只是检查对象是否没有普通ID,然后用发送过来的有效负载替换内容。它不仅可以执行此操作,还可以某种方式更新具有相同uid的所有先前对象,即使if语句不针对它们运行。

const rootReducer = (state = initState, action) => {
  if (action.type === "ADD_POKEMON") {
    let foundFirstEmptyPoke = false;

    const newArray = state.party.map((pokemon, index) => {
      if (typeof pokemon.id === "undefined" && foundFirstEmptyPoke === false) {
        foundFirstEmptyPoke = true;
        pokemon = action.payload; // set the data to the first object that ios empty
      }
      // if we get to the last pokemon and it's not empty
      if (index === 5 && foundFirstEmptyPoke === false) {
        pokemon = action.payload; // replace the last pokemon with the new one
      }
      return pokemon;
    });
    return {
      party: newArray
    };
  }
  return state;
};

3 个答案:

答案 0 :(得分:3)

这里的问题是,当您单击以选择一个神奇宝贝时,您会对从API中检索到的数据进行突变:

handleClick = pokemon => {
  pokemon.uid = Math.random(); // HERE
  this.props.addToParty(pokemon);
};

您实际上改变了反应状态。您应该做的是克隆您的pokemon数据对象,向刚生成的克隆中添加一个uid,并使用它更新您的redux状态:

handleClick = pokemon => {
  this.props.addToParty({
    ...pokemon,
    uid: Math.random()
  });
};

这样,就不会保留对实际反应状态的引用。因为这就是您说it updates the old squirtle with the new squirtles uid时发生的事情。当您尝试添加其他神奇宝贝时,您更新了从API检索到的数据,该数据也从您的第一个神奇宝贝插槽(从您的redux状态)引用。

答案 1 :(得分:1)

在react / redux中,最好不要突变对象:

this.props.addToParty({...pokemon, uid: Math.random()});

答案 2 :(得分:0)

您正在改变状态。在更新之前,请使用扩展语法***复制状态。

return {
...state,
party: newArray
}