如何在Immer Draft中更新多维数组/对象数组,避免页面卡顿崩溃
问题分析与解决方案
你的直接赋值操作本身在Immer的使用逻辑上没有错误,但页面变慢甚至崩溃的问题大概率不是出在Immer的赋值步骤,而是其他环节导致的。以下是具体的排查和优化方向:
1. 检查新数组的生成逻辑
如果modifiedArrayOfArrays的生成过程中存在大量冗余计算,或者每次都完全重建所有子数组(哪怕子数组内容没变化),会产生大量新的对象/数组引用,这会触发React组件的深层重渲染。
- 优化思路:只对实际发生变化的子数组进行更新,复用未变化的子数组引用。比如遍历原数组时,对比子数组内容,仅替换需要更新的部分,而不是生成全新的二维数组。
2. 优化React组件的渲染逻辑
这往往是大数组更新导致页面卡顿的核心原因:
- 确保渲染数组元素的子组件使用
React.memo包裹,避免子组件在props未变化时重复渲染; - 使用
reselect创建缓存的选择器,在useSelector中精准获取需要的数组片段,而不是直接获取整个大数组,减少不必要的state订阅; - 如果子组件的key值设置不合理(比如用索引当key),会导致React无法正确复用DOM节点,也会引发性能问题,确保key值是唯一且稳定的标识。
3. Immer的高效使用方式
如果确实需要替换整个数组,直接赋值draft.someArrayofArrays = modifiedArrayOfArrays是没问题的,但如果是局部更新场景,建议直接操作draft的具体元素,而不是生成整个新数组:
// 局部更新示例:修改第n个子数组 draft.someArrayofArrays[n] = updatedSubArray; // 或者修改子数组中的某个元素 draft.someArrayofArrays[n][m] = newValue;
这种方式下Immer只会修改变化的部分,生成的新state中未变化的子数组会保留原有引用,从而减少组件重渲染的触发。
4. 排查其他性能瓶颈
比如数组规模过大时,是否在组件渲染中做了同步的 heavy 计算(比如在render函数里过滤、排序数组),这类操作应该放到useMemo中缓存结果,避免每次渲染都重复执行。
内容的提问来源于stack exchange,提问作者Mayank Singh
相关产品推荐
相关产品推荐

