FlashList滚动复用项时显示加载器/骨架屏方案咨询
解决方案
一、解决返回顶部卡片重渲染问题
问题根源在于使用index作为列表项的key,当列表滚动或数据变动时,index会发生变化,导致FlashList销毁旧组件并重建新组件。将key替换为帖子唯一标识item.feed_id即可稳定组件身份,避免不必要的重渲染:
// 在renderItem中修改FeedsCardLayout的key属性 <FeedsCardLayout key={item.feed_id} // 替换原有的key={index} showEdit={diff} // 其他属性保持不变 />
二、解决快速滚动出现空白的问题
通过优化FlashList配置+添加占位加载组件(Shimmer)填补渲染间隙:
1. 优化FlashList渲染配置
添加getItemLayout属性,提前告知列表每个项的高度,减少动态布局计算时间;调整estimatedItemSize为实际卡片的准确高度,提升滚动流畅性:
// 在FlashList组件中添加getItemLayout <FlashList data={feedList} renderItem={renderItem} ListFooterComponent={renderFooter} // 添加getItemLayout getItemLayout={(data, index) => ({ length: 362, // 替换为卡片实际高度,和estimatedItemSize一致 offset: 362 * index, index, })} estimatedItemSize={362} // 确保和实际卡片高度匹配 // 其他属性保持不变 />
2. 添加Shimmer占位组件
第一步:创建Shimmer占位组件
// 可单独创建组件文件,或直接在当前文件中定义 const ShimmerCard = ({ colors }) => { return ( <View style={{ height: 362, marginBottom: wp(10), backgroundColor: colors.grey, borderRadius: wp(10), padding: wp(15), }}> <View style={{ height: hp(5), width: wp(30), backgroundColor: colors.lightGrey, borderRadius: wp(5), marginBottom: wp(10), }} /> <View style={{ height: hp(20), width: '100%', backgroundColor: colors.lightGrey, borderRadius: wp(10), marginBottom: wp(10), }} /> <View style={{ flexDirection: 'row', justifyContent: 'space-between', }}> <View style={{ height: hp(4), width: wp(25), backgroundColor: colors.lightGrey, borderRadius: wp(5), }} /> <View style={{ height: hp(4), width: wp(20), backgroundColor: colors.lightGrey, borderRadius: wp(5), }} /> </View> </View> ); };
第二步:在renderItem中集成占位逻辑
根据实际数据就绪状态判断,未加载完成时显示Shimmer:
const renderItem = ({ item, index }) => { const endDate = moment(item.created_at).add(5, 'hours').add(45, 'minutes'); const todaysdate = moment(); const diff = endDate > todaysdate; // 可根据实际数据(如视频/图片是否加载完成)调整判断条件 const isLoading = !item?.content || !item?.created_at; if (isLoading) { return <ShimmerCard colors={colors} />; } return ( <FeedsCardLayout key={item.feed_id} showEdit={diff} callback={() => { callback(item.feed_id); }} residentId={residentId} data={item} bottomCallback={(callbackType, data) => { bottomCallback(callbackType, data, index); }} shareCallback={shareCallback} pollCallback={(selectedOption, pollData) => { pollCallback(selectedOption, pollData, index); }} menuCallback={callbackType => { menuCallback(callbackType, item, index); }} /> ); };
额外优化建议
- 调整
maxToRenderPerBatch和initialNumToRender:将initialNumToRender设为屏幕可见卡片数(比如2),减少初始渲染压力 - 对
FeedsCardLayout中的媒体资源(视频、图片)添加懒加载和缓存,避免重复加载 - 确保
feedList数据稳定性,避免频繁修改数组引用(使用immutable数据或浅拷贝更新)
内容的提问来源于stack exchange,提问作者PRANESH
相关产品推荐
相关产品推荐

