依赖于prevState 的setState 赋值方式(特别是格式为对象数组时)
在React 的useState hook里,当state的变化依赖于prevState时,使用setState 赋值时需要采用“传入函数”的方法。
(警告:此时直接赋值newState 可能被React 的优化算法折叠,而无法达到预期效果)
例:(传入函数的一种优良示例)
以例子中方式赋值的优点(对比一些别的方式):
1. 如下这样的赋值,React 无法感知zone 的存储变化,所以component re-render 都不会触发
// error 错误示例! setZone(prevZone => prevZone[*].clicked = !prevZone[*].clicked)
2. 使用深拷贝改变prevZone 的存储指针,简单粗暴,但是性能和内存消耗比较大。(旧内存的所有存储地址全部变化,没有复用内存可言)
// 深拷贝 setZone(prevZone => { const cloneZone = _.cloneDeep(prevZone) cloneZone[*].clicked = !cloneZone[*].clicked })
综上:
示例方式通过map方法,只改变最外层内存指针变化,以及在唯一需要新开内存的对象上重新开内存赋值。比较符合内存的合理使用。
import { useState } from 'react';
export default function App() {
const [zone, setZone] = useState([
{ id: 1, clicked: false },
{ id: 2, clicked: false },
])
const toggleCircle = id => {
setZone(prevZone => {
return prevZone.map(item => item.id === id ? { ...item, clicked: !item.clicked } : item)
})
}
return (
{zone.map(item => (
<li
key={item.id}
onClick={() => toggleCircle(item.id)}
>
{item.id}
))}
)
}