即使设置了唯一的关键点,react也会重复重复关键点



我有一个由6个对象组成的数组,其中有一个uid,没有其他任何对象。这样我就可以重复它们,并拥有一些占位符内容,直到一个对象准备好添加到数组中。当选择新对象时,我设置了一个唯一的关键点。但是,如果我选择同一个对象两次,即使我设置了一个唯一的关键点。它似乎更新了重复项上的唯一密钥(即使唯一密钥不同)。

在这里可能更容易看到代码/应用程序的运行,问题的一个例子是单击"喷射",然后单击"释放",记下显示的uid。然后再次单击"喷射",由于某种原因,它会用新的喷射器uid更新旧的喷射器,从而导致重复的密钥错误。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。它本质上只是检查对象是否没有正常的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);
};

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

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

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

在react/redux中,最好不要更改对象:

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

您正在更改状态。使用排列语法***在更新前复制状态。

return {
...state,
party: newArray
}

最新更新