React组件state更新后未触发重新渲染该如何解决?
问题原因
- React 状态更新的触发逻辑依赖引用变化检测:对于数组、对象这类引用类型的 state,React 会通过比较新旧 state 的内存引用是否变化来判断是否需要触发重渲染,不会默认深度比对内部的内容变化。
- 你的代码中
let currentStudents = students直接赋值了原 state 数组的引用,后续修改数组元素、排序都是直接在原数组实例上做的可变修改,新旧 state 指向同一个内存地址,所以调用setStudents时 React 认为 state 没有变化,跳过了重渲染,这也是你打印currentStudents === students得到true的原因。
修复方案
核心原则是每次更新数组/对象类型的 state 时,创建一个全新的实例,而不是修改原 state 的内容:
function updateStudent(item, tab) { // 基于原数组浅拷贝生成全新的数组实例 let currentStudents = [...students]; // 浅拷贝要修改的学生对象,避免直接修改原对象引用 let studentToUpdate = {...item}; const idx = currentStudents.findIndex((value) => { return value.uid === item.uid; }); if (studentToUpdate.status === 4) { studentToUpdate.status = 0 } else { studentToUpdate.status++ } currentStudents[idx] = studentToUpdate currentStudents.sort((a, b) => { return a.status - b.status }) // 此时传入的是全新数组,引用和原state不同,会正常触发重渲染 setStudents(currentStudents) }
- 如果你的学生对象存在更深层级的嵌套属性,需要根据情况做对应层级的拷贝,也可以使用 Immer 这类不可变数据工具简化操作。
内容的提问来源于stack exchange,提问作者Krom
相关产品推荐
相关产品推荐

