gpt4 book ai didi

javascript - 如何正确删除 React 状态数组中的元素?

转载 作者:行者123 更新时间:2023-12-02 21:52:12 24 4
gpt4 key购买 nike

基于状态数组创建组件并为每个组件提供数组的 setState 属性会导致奇怪的行为。也许是由于并行状态变化?尝试下面的代码片段。单击一个方 block 应该将其删除。相反,最后创建的方 block 总是会被删除。

问题似乎出在 Square 组件中的 useEffect() 中。虽然在代码片段中它确实没有用,但我使用类似的东西来使元素可拖动。有人可以解释这种行为并提出解决方案吗?我觉得我在这里错过了一些有关 React 的重要内容。

function Square(props){
const [pos, setPos] = React.useState([props.top, props.left])

React.useEffect(() => {
props.setSquares(prevState => prevState.map((square, index) => index === props.index ? {...square, top: pos + 20} : square
))
}, [pos])

function deleteMe(){
props.setSquares(prevState => prevState.filter((square, index) => index !== props.index))
}

return <div onClick={deleteMe}
style={{top: pos[0]+'px', left: pos[1]+'px'}}
className='square'>
</div>
}

function App(){
const [squares, setSquares] = React.useState([
{top: 20, left: 0},{top: 20, left: 100},
{top: 20, left: 200},{top: 20, left: 300}])

React.useEffect(() => console.log('rerender', ...squares.map(s => s.left)))

return <div>{squares.map((square, index) => <Square
setSquares={setSquares} index={index}
top={square.top} left={square.left}/>)}</div>
}
ReactDOM.render(<App/>, document.getElementById('root'))
.square{
position: absolute;
width: 80px;
height: 80px;
background: orange;
}
<div id='root'></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js"></script>

编辑:正如 Nick 在评论中建议的那样,我更改了 setSquare 方法以使用 prevState.mapfilter 以免不自觉地改变之前的状态。

问题仍然存在......最后一个方 block 总是在屏幕上消失。对每次重新渲染使用效果表明状态已正确更新。我在这里缺少什么?

最佳答案

您必须记住,展开运算符是一个副本,即以下代码中的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;
});
})

关于javascript - 如何正确删除 React 状态数组中的元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60105053/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com