如何在修改状态时避免FlatList出现不必要的重新渲染
问题原因
你遇到的FlatList全量重渲染由以下几个可优化点导致:
- 父组件状态
isModalDeleteVisible变更时触发整个父组件重渲染,你定义的listRenderItem、keyExtractor没有做缓存,每次重渲染都会生成新的函数引用,FlatList感知到渲染配置变化就会触发所有子项重渲染 onDelete的useCallback依赖了isModalDeleteVisible,每次状态更新都会生成新的函数引用,虽然此处未传递给子组件,但写法本身可以进一步优化- 子组件
Children没有做渲染缓存,即使接收的props没有变化,只要父组件触发renderItem执行,子组件就会重渲染
修复步骤
1. 优化onDelete的缓存逻辑
使用setState的函数式更新写法,移除对isModalDeleteVisible的依赖,保证onDelete引用永远不变:
const onDelete = useCallback( () => setModalDeleteVisible(prev => !prev), [] )
2. 缓存FlatList相关的渲染函数
把listRenderItem和keyExtractor都用useCallback缓存,避免每次父组件重渲染生成新的函数引用:
// 也可以直接把keyExtractor写在组件外部,完全脱离组件渲染周期 const keyExtractor = useCallback((item) => item.id, []) const listRenderItem = useCallback(({ item, index }) => { return ( <Children item={item} index={index} /> ) }, [])
如果listRenderItem内部依赖了其他外部变量,记得把对应变量加到useCallback的依赖数组中。
3. 给子组件加渲染缓存
用React.memo包裹Children组件,只要传入的props浅比较相等,就不会触发子组件重渲染:
// Children.js import { memo } from 'react' const Children = ({ item }) => { console.log(item.id) return ( // 原有渲染逻辑 ) } export default memo(Children)
额外注意
如果你的dataList是每次父组件重渲染都会生成的新引用(比如接口返回后每次都生成新数组、或者在组件内直接写死的数组字面量),还需要用useState或者useMemo缓存dataList的引用,避免FlatList感知到数据变化触发重渲染。
内容的提问来源于stack exchange,提问作者Gaylord.P
相关产品推荐
相关产品推荐

