如何避免FlatList中重复渲染相同id的列表项?
解决方案
核心思路有两种,优先推荐第一种预处理数据源的方案:
方案1:预处理数据源(推荐)
直接对原始数据做去重+筛选,得到纯净的待渲染收藏列表,不需要在渲染逻辑里加额外判断,性能最优,逻辑最清晰:
// 按id对原始商品数组去重,默认保留每个id出现的第一条数据,如有特殊保留规则可自行调整判断逻辑 const uniqueProductMap = new Map(); dataArray.forEach(item => { if (!uniqueProductMap.has(item.id)) { uniqueProductMap.set(item.id, item); } }); // 筛选得到仅包含用户收藏的商品列表,过滤不存在的id const renderFavList = myFavIds.map(id => uniqueProductMap.get(id)).filter(Boolean);
修改FlatList的数据源为处理后的列表,同时把keyExtractor改成用item.id,避免index作为key带来的渲染异常:
<FlatList data={renderFavList} renderItem={renderItem} keyExtractor={(item) => item.id} /> // 现在renderItem不需要再做id判断,逻辑更简洁 const renderItem = ({item, index}) => { return ( <IndividualProduct info={item} index={index} fav={true} stateChange={stateChange} setLoading={setLoading} /> ); };
方案2:渲染时过滤(仅应急使用)
如果不想改动数据源逻辑,可以用useRef存储已经渲染过的id,渲染时判断去重,注意该方案性能较差,且列表更新时需要手动清空已记录的id:
import { useRef, useEffect } from 'react'; // 组件内定义ref存储已渲染的id,避免组件重渲染时记录丢失 const renderedIdSet = useRef(new Set()); const renderItem = ({item, index}) => { // 同时判断是否在收藏列表、且未被渲染过 if (myFavIds.includes(item.id) && !renderedIdSet.current.has(item.id)) { renderedIdSet.current.add(item.id); return ( <IndividualProduct info={item} index={index} key={index} fav={true} stateChange={stateChange} setLoading={setLoading} /> ); } return null; }; // 收藏列表更新时清空已记录的id,避免后续渲染异常 useEffect(() => { renderedIdSet.current.clear(); }, [myFavIds]);
内容的提问来源于stack exchange,提问作者Kerry
相关产品推荐
相关产品推荐

