Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/437.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何正确地从React状态数组中删除元素?_Javascript_Reactjs_React State Management_React State - Fatal编程技术网

Javascript 如何正确地从React状态数组中删除元素?

Javascript 如何正确地从React状态数组中删除元素?,javascript,reactjs,react-state-management,react-state,Javascript,Reactjs,React State Management,React State,基于状态数组创建组件并为每个组件赋予数组setState属性会导致奇怪的行为。可能是由于并行状态的改变?尝试下面的代码片段。点击一个正方形会将其删除。相反,创建的最后一个正方形将被删除 问题似乎在于Square组件中的useffect()。虽然在代码片段中它真的没有什么用处,但我使用了类似的方法使元素可以拖动。有人能解释这种行为并提出解决方案吗?我觉得我错过了一些重要的事情 功能广场(道具){ const[pos,setPos]=React.useState([props.top,props.

基于状态数组创建组件并为每个组件赋予数组setState属性会导致奇怪的行为。可能是由于并行状态的改变?尝试下面的代码片段。点击一个正方形会将其删除。相反,创建的最后一个正方形将被删除

问题似乎在于
Square
组件中的
useffect()
。虽然在代码片段中它真的没有什么用处,但我使用了类似的方法使元素可以拖动。有人能解释这种行为并提出解决方案吗?我觉得我错过了一些重要的事情

功能广场(道具){
const[pos,setPos]=React.useState([props.top,props.left])
React.useffect(()=>{
props.setSquares(prevState=>prevState.map((square,index)=>index==props.index?{…square,top:pos+20}:square)
))
},[pos])
函数deleteMe(){
props.setSquares(prevState=>prevState.filter((正方形,索引)=>index!==props.index))
}
返回
}
函数App(){
常数[squares,setSquares]=React.useState([
{top:20,left:0},{top:20,left:100},
{top:20,left:200},{top:20,left:300}])
React.useffect(()=>console.log('rerender',…squares.map(s=>s.left)))
返回{squares.map((squares,index)=>)}
}
ReactDOM.render(,document.getElementById('root'))
.square{
位置:绝对位置;
宽度:80px;
高度:80px;
背景:橙色;
}

您必须记住,spread操作符是一个浅拷贝,这意味着下面代码中的
newSquares[props.index].top=pos[0]+20
正在对当前状态数组中的对象进行变异

props.setSquares(prevState => {
  const newSquares = [...prevState]
  newSquares[props.index].top = pos[0] + 20 // this is mutating current state
  return newSquares
})
解决此问题的一个方法是:

props.setSquares(prevState => {
  const newSquares = [...prevState]
  newSquares[props.index] = { 
    ...newSquares[props.index],
    top: pos[0] + 20
  };
  return newSquares
})
另一个选项是只映射到现有状态,并为要更改的元素返回新的内容:

props.setSquares(prevState => {
  return prevState.map((el, i) => {
    return i === props.index ? { ...el, top: pos[0] + 20 } : el;
  });
})

谢谢你的建议。我假设浅层复制不会有害,因为它发生在
setSquares
方法中,
prevState
只是一个局部变量,对吗?在这里处理
prevState
不会对当前状态产生影响。同样,正确的拷贝(如由
map
生成)也会导致相同的行为。而
console.log(squares)
恰好在
App
s返回之前显示正确的squares已从状态中删除,在屏幕上,错误的一个消失了我不相信
prevState
是状态对象的深层副本,即使在回调函数中也是如此——相当肯定这会非常低效。我认为在这个示例中,您将重新分配和变异混为一谈。一个更合适的例子是,如果您声明的是一个对象,并且您正在修改该对象的一个属性,那么您当然是绝对正确的。我稍微改变了一下主意。我仍然坚信,不能在
setState
中处理
prevState
prevState
与当前状态无关的问题意味着React必须在引擎盖下进行深度复制,这将是非常低效的,因为依赖于状态的每个组件都会重新渲染