React Native中useState更新触发FlatList全量重渲染该如何优化?
React Native FlatList 点击列表项全量重渲染优化方案
问题根因
你当前将控制按钮显示的状态x定义在App根组件下,x更新时会触发整个App组件重渲染,作为子组件的FlatList也会跟着重新执行渲染逻辑,导致所有列表项无差别重绘,大数据量下就会出现卡顿。
可行优化方案
方案1:组件拆分搭配memo、useCallback缓存(适配当前状态在列表外的场景)
核心思路是通过React.memo缓存不需要重渲染的组件,只有props发生变化时才触发重绘,步骤如下:
- 抽离列表项为独立组件,用
React.memo包裹 - 抽离FlatList为独立组件,用
React.memo包裹,避免父组件状态更新时连带重渲染 - 用
useCallback缓存点击事件函数,避免每次渲染生成新函数导致memo缓存失效 - 配置
keyExtractor给列表项指定唯一标识,优化React diff效率
优化后完整代码如下:
import React, {useState, memo, useCallback} from "react" import {View, FlatList, Text, TouchableOpacity, Button} from "react-native" // 缓存列表项组件,仅props变化时重渲染 const ListItem = memo(({item, onPress}) => { return ( <View> <TouchableOpacity onPress={onPress}> <Text style={{padding: 10}}>{item}</Text> </TouchableOpacity> </View> ) }) // 缓存FlatList组件,静态数据无变化时不会重渲染 const StaticFlatList = memo(({onItemPress}) => { // 静态数据放在组件内部,避免每次渲染生成新数组触发重绘 const listData = ["-", "--", "---", "----", "-----", "------", "-------", "--------", "---------"] return ( <FlatList data={listData} keyExtractor={(item, index) => index.toString()} renderItem={({item}) => <ListItem item={item} onPress={onItemPress} />} /> ) }) export default function App() { const [x, setX] = useState(false) // 缓存点击事件,避免生成新函数导致memo失效 const handleItemPress = useCallback(() => { setX(true) }, []) return( <View> <StaticFlatList onItemPress={handleItemPress} /> {x && <Button title="It works" onPress={() => console.log("Everything is working")} />} </View> ) }
方案2:状态下移(适配状态仅列表项内部使用的场景)
如果控制显示的状态不需要在FlatList外部使用,直接把状态下移到对应的列表项组件内部,点击时只有当前被点击的列表项会重渲染,其他组件完全不受影响。
额外性能优化
如果列表项高度固定,给FlatList添加getItemLayout属性预计算布局,大数据量下性能提升效果非常明显:
// 示例中列表项高度为50,可根据实际样式调整 getItemLayout={(data, index) => ({ length: 50, offset: 50 * index, index })}
注:你提供的原始代码存在几个语法问题:
Flatlist首字母L需要大写、未导入TouchableOpacity和Button组件、export default const写法不合法,上述优化代码已同步修正。
内容的提问来源于stack exchange,提问作者Henrik
相关产品推荐
相关产品推荐

