我在React中看到了意想不到的结果。StrictMode调用了我的useReducer函数两次-我正在交换数组中的元素,但StrictMode导致我的交换将元素跳转到两个插槽,而不是期望的一次。我不确定这段代码的“不纯”是什么?
case 'swap_section': {
let modified_song = {...song}
let target_section_index = modified_song.song.songsheet.aSections.findIndex(
section => action.daw === section.daw
)
let target_section = modified_song.song.songsheet.aSections[target_section_index]
let swap_section_index = action.direction === "down"
? target_section_index + 1 : target_section_index - 1
// StrictMode calling this twice may attempt to swap w/ (final index + 1) - check index & undefined
if(swap_section_index > -1 && swap_section_index < modified_sections.length) {
let swap_section = modified_song.song.songsheet.aSections[swap_section_index]
if(swap_section) {
modified_song.song.songsheet.aSections[swap_section_index] = target_section
modified_song.song.songsheet.aSections[target_section_index] = swap_section
return modified_song
}
}
return modified_song
}
1条答案
按热度按时间xzv2uavs1#
代码不是pure,因为外部的值
song.song
被修改了 (我假设“外部”是你没有显示的代码)。对象标识
你显然是想创建一个
song
对象的副本,但是你的方法并没有“深复制”这个对象,也就是下面这行:将
song
的所有属性复制到modified_song
,modified_song
现在是与song
不同的对象,但modified_song
的所有属性仍然具有与song
的属性相同的(相同的)值,即modified_song.song
与song.song
相同。现在,当您修改
modified_song.song
时,您也在修改song.song
(并且下一次执行代码时,输入是不同的)。解决方案
您需要复制最后一个属性,保持原始属性不变,并仅使用副本,例如:
修改原件
直接更改
modified_song.song...
不是在React中应该采用的方式。如果您认为需要将结果写回
song.song...
,可能有某种方法可以重构状态管理,或者您可以在某个事件中调用状态更改,......但我真的不能说,我需要更多的信息来找到特定的解决方案。