FlatList大数据量时点击复选框状态更新卡顿,如何优化性能?
React Native FlatList 大量数据下点击Checkbox卡顿问题解决
问题描述
当FlatList数据量达数百条(如700条)时,点击列表项的Checkbox会出现严重卡顿:首次点击耗时约1秒,后续每次点击耗时递增20%,最终稳定在2.5秒左右。经排查,性能瓶颈出现在contactPhoneNumberList2状态变更后的全量重渲染。
根本原因
每次状态更新后,FlatList的所有列表项都会重新执行_renderItem函数,且每个列表项都通过find方法遍历选中列表判断状态,同时没有任何组件记忆化处理,导致大量不必要的计算和渲染操作,随着选中项增加,耗时逐步累积。
优化方案
1. 用Set存储选中状态,提升查找效率
将选中的手机号列表从数组改为Set,has方法的时间复杂度为O(1),远优于数组的find(O(n)),同时减少状态更新时的数组拷贝开销。
2. 抽离子组件并使用React.memo缓存
把列表项抽成独立组件,用React.memo包裹,只有当组件的props(如item、isSelected、onPress)变化时才会重渲染,避免全量列表项跟着父组件状态变更而重渲染。
3. 使用函数式状态更新+useCallback缓存事件
避免依赖旧状态的引用,确保状态更新的准确性;同时用useCallback缓存点击事件,避免子组件因函数引用变化触发不必要的重渲染。
修改后的完整代码
import React, { useState, useCallback } from 'react'; import { FlatList } from 'react-native'; import { ListItem } from '@rneui/themed'; // 根据实际使用的UI库调整 // 抽离列表项子组件,用React.memo缓存 const ContactItem = React.memo(({ item, isSelected, onPress }) => { return ( <ListItem> <ListItem.CheckBox checked={isSelected} onPress={onPress} /> <ListItem.Content> <ListItem.Title>{item.mobileNo}</ListItem.Title> </ListItem.Content> </ListItem> ); }); const TestScreen = () => { // 构建测试数据集,实际场景从Redux获取 const contactList = Array.from({ length: 700 }, (_, i) => ({ mobileNo: i.toString() })); // 用Set存储选中的手机号,提升查找效率 const [selectedNumbers, setSelectedNumbers] = useState(new Set()); // 用useCallback缓存点击事件,避免子组件重复接收新函数 const handlePress = useCallback((item) => { setSelectedNumbers(prev => { const newSet = new Set(prev); if (newSet.has(item.mobileNo)) { newSet.delete(item.mobileNo); } else { newSet.add(item.mobileNo); } return newSet; }); }, []); const renderItem = ({ item }) => { const isSelected = selectedNumbers.has(item.mobileNo); return ( <ContactItem item={item} isSelected={isSelected} onPress={() => handlePress(item)} /> ); }; return ( <FlatList data={contactList} keyExtractor={(item) => item.mobileNo} // mobileNo唯一,无需额外拼接索引 renderItem={renderItem} initialNumToRender={10} maxToRenderPerBatch={10} windowSize={10} /> ); }; export default TestScreen;
额外优化提示
- 若数据来自Redux,使用
createSelector创建记忆化的选择器,避免父组件因Redux状态微小变化触发重渲染。 - 自定义ListItem组件时,避免在render函数内部创建新函数或对象,确保props的稳定性。
内容的提问来源于stack exchange,提问作者Bilal Abdeen
相关产品推荐
相关产品推荐

