我有一个包含 6 个对象的数组,这些对象只有一个 uid,没有其他任何东西。这样我就可以重复它们并拥有一些占位符内容,直到准备好将对象添加到数组中。选择新对象时,我设置了一个唯一键。但是,如果我两次选择同一个对象,即使我设置了唯一键。它似乎更新了重复项目的唯一键(即使唯一键不同)。
可能更容易看到代码/应用程序在这里运行,问题的一个例子是点击 squirtle 然后 blastoise,记下显示的 uid。然后再次单击 squirtle,由于某种原因,它会使用新的 squirttles uid 更新旧的 squirttle,从而导致重复键错误。 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);
};
然后这会调用触发以下 reducer 的分派(dispatch)。这实际上只是检查对象是否没有正常 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;
};
最佳答案
这里的问题是,当您单击选择一个 pokemon 时,您会改变从 API 检索到的数据:
handleClick = pokemon => {
pokemon.uid = Math.random(); // HERE
this.props.addToParty(pokemon);
};
你实际上改变了 react 状态。你应该做的是克隆你的 pokemon 数据对象,将一个 uid 添加到你刚刚生成的克隆并用它更新你的 redux 状态:
handleClick = pokemon => {
this.props.addToParty({
...pokemon,
uid: Math.random()
});
};
这样,就不会保留对实际 react 状态的引用。因为当您说 它用新的 squirttles uid 更新旧的 squirtles
时,这就是发生的事情。当您尝试添加另一个 pokemon 时,您更新了从 API 检索到的数据,这些数据也从您的第一个 pokemon 插槽(从您的 redux 状态)中引用。
关于javascript - 即使在设置唯一键时也会 react redux 重复键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54365974/