使用React.memo后React Native列表与弹窗组件仍出现重渲染是什么原因
问题原因
- 子组件嵌套定义:你将
Item组件分别定义在Bosses和ModalDrops组件内部,每次父组件重渲染时,Item的构造引用都会完全重置,React.memo会判定为全新组件,直接触发重新挂载渲染,完全失去缓存作用。 - 错误的keyExtractor实现:弹窗内FlatList的
keyExtractor返回随机值,每次渲染时所有列表项的key都会变化,FlatList会判定所有元素都是新增的,直接销毁全部旧节点重新渲染,这是滚动时触发重渲染的核心原因。 - 回调函数未做引用稳定化:
renderItem、ListEmptyComponent、rowRenderer等作为组件props传递的回调函数,都没有用useCallback包裹,每次渲染都会生成新的引用,触发下游组件props变化导致重渲染。 - 不稳定的依赖项:
Bosses组件内的modals每次渲染都会重新生成数组,导致依赖它的openModalDrop每次都生成新的引用,进一步触发列表项重渲染;layoutProvider也没有做memo缓存,每次渲染都会生成新实例,触发RecyclerListView重渲染。 - 状态更新次数叠加:点击打开弹窗时先执行
setDropRef触发一次Bosses组件重渲染,之后modal打开的动画/状态变更又会触发1-2次重渲染,叠加后就出现了打开时重渲染2-3次的现象。
修复方案
- 把所有嵌套定义的子组件移到对应组件外部,不要在父组件作用域内声明子组件。如果子组件需要用到父组件的变量,通过props传递即可。
- 替换
keyExtractor的随机值实现,使用列表项的唯一业务id作为key,没有业务id的情况下临时用index代替也可,绝对不能返回随机值。 - 所有作为props传递的回调函数都用
useCallback包裹,静态配置项用useMemo缓存,比如layoutProvider、flatListProps里的静态配置都可以做缓存。 - 修正
modals的定义,改用ref存储模态框实例:const modals = React.useRef(Array(8).fill(null)),使用时通过modals.current访问,避免每次渲染重新生成数组。 - 若
React.memo的props包含对象/函数类型,可以传入第二个参数自定义比较逻辑,精准控制是否需要重渲染。
内容的提问来源于stack exchange,提问作者locklock123
相关产品推荐
相关产品推荐

