FlatList筛选数据时如何避免自定义项重渲染引发的图片闪烁
FlatList筛选重渲染导致图片闪烁修复方案
首先先修正示例代码中存在的基础语法错误,这些错误本身也会加剧重渲染问题:
FlatList的data属性错误传入了未定义的data变量,实际需要绑定维护的筛选后状态filteredDataImage和Text组件的属性写反:图片URI需要传入Image的source属性,产品名称需要放在Text组件的子节点位置- 筛选逻辑中传入
filterData的数据源未定义,需要传入原始全量数据initialData
修复后完整代码
import React, { useState } from 'react'; import { View, Text, Image, Button, FlatList } from 'react-native'; // 抽离独立的列表项组件,用React.memo包裹做渲染优化 const ProductListItem = React.memo(({ text, image }) => { return ( <View style={{padding: 12}}> <Text style={{fontSize: 16, marginBottom: 8}}>{text}</Text> <Image source={{ uri: image, cache: 'default' }} style={{ width: 200, height: 300, resizeMode: 'cover' }} /> </View> ); }); function ProductList() { const initialData = [ { text: 'product A', image: 'https://picsum.photos/200/300', id: 1 }, { text: 'product B', image: 'https://picsum.photos/200/300', id: 2 }, { text: 'product C', image: 'https://picsum.photos/200/300', id: 3 }, ]; const [filteredData, setFilteredData] = useState(initialData); const handleFilterPress = () => { setFilteredData(filterData(initialData)); }; // renderItem保持稳定引用,不要在组件return里内联定义 const renderItem = ({ item }) => { return <ProductListItem text={item.text} image={item.image} />; }; // 固定列表项高度时传入getItemLayout,跳过动态高度测量减少渲染开销 const getItemLayout = (_, index) => ({ length: 356, // 对应列表项总高度:图片300 + 内边距24 + 文本高度+边距32 offset: 356 * index, index, }); return ( <> <Button onPress={handleFilterPress} title="触发筛选" /> <FlatList data={filteredData} keyExtractor={(item) => item.id} renderItem={renderItem} getItemLayout={getItemLayout} removeClippedSubviews={true} /> </> ); } export default ProductList;
核心优化逻辑说明
- 用
React.memo包裹独立的列表项组件:默认父组件状态更新触发重渲染时,所有子组件会无差别重渲染,React.memo会对传入组件的props做浅比较,只有当props实际发生变化时才会重渲染对应项。筛选操作后保留的产品项id、名称、图片地址都没有变化,就不会触发不必要的重渲染,自然不会出现图片重复加载的问题。 - 不要在JSX内联写
renderItem或者匿名列表项组件:每次父组件重渲染都会生成新的函数/组件引用,直接破坏React.memo的浅比较判断,导致优化失效。 - 给
Image组件显式设置cache: 'default':强制复用同URI已下载的图片缓存,就算特殊情况触发组件重挂载,也不会重新发起网络请求拉取图片,从根源上避免图片加载导致的闪烁。 - 必须用唯一不变的id作为
keyExtractor的返回值,不要用数组索引作为key:筛选操作会改变数组顺序,用索引作为key会导致React错误复用组件实例,触发不必要的卸载和重挂载。 - 固定高度列表一定要传
getItemLayout:跳过FlatList动态测量列表项高度的计算过程,大幅减少渲染时的性能开销,避免列表抖动。
内容的提问来源于stack exchange,提问作者Daniele Ferrario
相关产品推荐
相关产品推荐

