React Hooks实现列表时数组state保存低效,求更优处理方案
React列表不可变更新性能问题解决方案
原生写法的合理性说明
React状态更新遵循不可变原则,要求每次更新返回新的状态引用,这样React可以通过浅对比快速判断状态是否变更,从而精准触发组件重渲染。如果直接调用原数组的push方法修改状态,数组引用不会发生变化,React会认为状态未更新,无法触发组件重渲染,导致界面不同步。
你担心的全量数组拷贝的性能开销,在绝大多数业务场景下都不需要在意:现代JS引擎对数组展开、slice等拷贝操作的优化非常成熟,即使是包含数千个元素的数组,拷贝耗时也在毫秒级,远低于界面渲染的开销,不会造成可感知的性能问题。
超大数组场景下的优化方案
如果你的列表元素量级达到十万级以上,且通过性能调试工具确认数组拷贝确实是性能瓶颈,可以选择以下优化方案:
- 使用Immer处理不可变更新
Immer是专门处理不可变数据的轻量库,基于Proxy实现,你可以直接修改状态草稿,它会自动生成新的不可变状态引用,不需要手动全量拷贝数组,比原生全量拷贝的性能高很多,代码写法也更简洁:
import { useImmerReducer } from 'use-immer'; function ListReducer(draft, action) { switch(action.type) { case 'push': // 直接修改草稿对象,无需手动拷贝数组 draft.push(action.data); break; } } const [state, dispatch] = useImmerReducer(ListReducer, []);
- 状态分片存储
将大数组拆分为多个子数组分组存储在状态中,每次push操作只需要拷贝对应分组的小数组,大幅降低单次拷贝的时间开销。
建议优先使用原生写法,不要提前做无意义的优化,只有确认性能瓶颈后再做对应调整即可。
内容的提问来源于stack exchange,提问作者Alex Li
相关产品推荐
相关产品推荐

