React中切换activeDate后列表更新异常:空响应仍显示旧数据
问题描述
我维护着一个带轮询和无限滚动的列表状态:
const [callListData, setCallListData] = useState<{results: Array<CallDataInterface>;}>(serverData);
- 每5秒通过
getData函数轮询更新数据,保证用户看到最新内容 - 向下滚动触发
page+1加载更多,向上滚动则page-1回退
目前遇到两个核心问题:
- 返回旧页码时,相同
data_id的记录有值变化,但无法刷新(原逻辑只会新增无ID的记录) - 切换
activeDate后,如果接口返回空数组[],第二次轮询后依然显示之前的列表数据,用useEffect监听activeDate清空状态也没解决
当前实现代码:
if (prevActiveDate.current !== activeDate) { prevActiveDate.current = activeDate; setListData(response.data); setDataMap({}); } else { const updatedDataMap = response.data.results.reduce( ( accumulator: Record<string, DataInterface>, item: CallDataInterface ) => { if (!accumulator[item.data_id]) { accumulator[item.data_id] = item; } return accumulator; }, { ...dataMap } ); setDataMap(updatedDataMap); const newData = Object.values(updatedDataMap) as DataInterface[]; setListData({ results: newData }); }
尝试过的无效处理:
useEffect(() => { setListData({ results: [] }); setDataMap({}); }, [activeDate]);
解决方案
核心问题分析
切换activeDate后第一次接口返回空数组时,prevActiveDate.current已经被更新为新日期,后续轮询会进入else分支,复用之前未完全清空的dataMap,导致旧数据残留;同时原逻辑不会覆盖已有ID的记录,导致旧数据无法更新。
修改后的代码实现
1. 调整接口响应处理逻辑
if (prevActiveDate.current !== activeDate) { prevActiveDate.current = activeDate; // 强制初始化新的dataMap,不管接口返回是否为空 const newDataMap: Record<string, DataInterface> = {}; // 仅当接口有数据时填充 if (response.data.results?.length) { response.data.results.forEach(item => { newDataMap[item.data_id] = item; }); } setDataMap(newDataMap); setListData({ results: Object.values(newDataMap) }); } else { const updatedDataMap = response.data.results.reduce( (accumulator: Record<string, DataInterface>, item: CallDataInterface) => { // 去掉存在性判断,直接覆盖相同ID的记录,保证数据更新 accumulator[item.data_id] = item; return accumulator; }, { ...dataMap } ); setDataMap(updatedDataMap); setListData({ results: Object.values(updatedDataMap) }); }
2. 完善activeDate切换时的副作用处理
useEffect(() => { // 切换日期时立即清空列表和映射表 setListData({ results: [] }); setDataMap({}); // 必须重置页码为1,避免请求旧页码的数据 setPage(1); // 可选:立即触发一次数据请求,不用等轮询 getData(1); }, [activeDate]);
关键优化点
- 去掉else分支中
accumulator[item.data_id]的存在性判断,确保相同ID的最新数据能直接覆盖旧记录 - 切换
activeDate时强制初始化新的dataMap,不再依赖接口返回的response.data结构,避免空数组导致的旧数据残留 - 切换日期时重置页码为1,从根源上避免加载旧日期的分页数据
内容的提问来源于stack exchange,提问作者annon_front_end
相关产品推荐
相关产品推荐

