React中如何监听useState定义的对象数组内部属性变更?
问题原因
- useState定义语法错误:你当前的代码对
React.useState做了赋值操作而非调用,正确用法应为React.useState(初始值)而非React.useState = (初始值)。 - 核心触发异常原因:React对状态更新、useEffect依赖项的对比都采用浅比较(引用地址对比)。你在
handleUpdate中直接修改了原数组的内部属性,let v = user仅复制了数组的引用,指向的还是同一块内存地址的原数组,传入setUser的依旧是原数组引用,React判定状态没有发生变化,因此不会触发重渲染,也不会触发依赖user的useEffect。 - 你在
setUser后直接打印user能看到修改后的值,是因为你直接篡改了原状态的内部属性,且setUser是异步更新,当前作用域下的user还是旧的闭包值,这个打印结果不代表React已经完成了状态更新。
解决方法
1. 修正useState定义
将赋值写法改为调用useState生成状态:
// list of user const [user, setUser] = React.useState([ { name: 'Tom', age: 23 }, { name: 'Marry', age: 24 }, { name: 'Dan', age: 22 }, { name: 'Rose', age: 22 }, { name: 'Alice', age: 23 } ])
2. 按照不可变原则修改状态
修改数组/对象类型的状态时,需要返回全新的引用,不要直接修改原状态:
function handleUpdate() { // 浅拷贝数组生成新引用 const newUserList = [...user] // 浅拷贝要修改的对象,避免修改原对象 newUserList[1] = {...newUserList[1], age: 99} setUser(newUserList) }
如果是深层嵌套的对象,你可以使用深拷贝,或者引入immer库简化不可变数据的编写:
import { produce } from 'immer' function handleUpdate() { setUser(produce(draft => { draft[1].age = 99 })) }
修改完成后,状态引用会发生变化,依赖user的useEffect就会正常触发。
内容的提问来源于stack exchange,提问作者Kmp
相关产品推荐
相关产品推荐

