关闭再打开含material-table的React组件时内存泄漏、渲染变慢的原因是什么?
外部定义columns导致卡顿、内存泄漏的原因
material-table 存在原地修改传入配置项的设计逻辑:组件挂载时会直接往你传入的 columns 数组、以及数组内的每一个列配置对象上,挂载内部状态、缓存数据、事件监听等运行时内容。
当 columns 定义在组件外部时,它属于全局作用域下的固定引用,页面不刷新就不会被销毁。每次MTable组件卸载后重新挂载,material-table都会往同一个columns引用上追加新的内部数据,挂载次数越多,columns上累积的冗余数据、无效事件监听就越多,不仅会大幅拖慢表格初始化速度,这些没有被正确释放的引用也会导致内存泄漏。
移到组件内部后的变化
把columns定义到组件内部后,每次MTable组件挂载都会生成一个全新的columns数组实例,和上一次挂载的配置引用完全独立。组件卸载时,这个仅在组件内部使用的columns实例没有任何外部引用持有,会被JS垃圾回收机制自动清理,连同material-table挂载在它上面的所有内部数据、监听函数一起被销毁。下次组件重新挂载时又会生成全新的配置实例,不会出现冗余数据累积的问题,自然解决了卡顿问题。
额外补充
常规React开发中通常建议把静态配置放到组件外部,避免不必要的重渲染,但这一规则不适用于会原地修改传入prop的第三方库。如果不想每次组件重渲染都生成新的columns实例,也可以用依赖为空的useMemo或者useRef包裹配置,但前提是确认第三方库不会修改传入的引用。对于material-table这个场景,直接把配置定义在组件内部是成本最低的解决方案。
内容的提问来源于stack exchange,提问作者ChivalrouS

