无限滚动加载重复数据怎么办?

晶晶 阅读 3

我在做商品列表的无限滚动,用的是 IntersectionObserver 监听底部元素。但每次滚动到底部触发加载后,新数据总是和之前的一样,明明接口传的 page 参数是递增的。

我检查了请求,发现 page 确实在变,但返回的数据还是第一页的内容。是不是我状态没更新对?比如这里我用了 setPage(page + 1),但可能因为闭包问题没拿到最新值?

useEffect(() => {
  const observer = new IntersectionObserver((entries) => {
    if (entries[0].isIntersecting && !loading) {
      setPage(page + 1); // 这里可能有问题?
      fetchData(page + 1);
    }
  });
  if (bottomRef.current) observer.observe(bottomRef.current);
  return () => observer.disconnect();
}, [loading]);
我来解答 赞 2 收藏
二维码
手机扫码查看
1 条解答
闲人奕诺
问题出在你调用 fetchData 的时候。你在 useEffect 里直接用了 page + 1 作为参数,但这个值可能不是最新的。记住 React 的状态更新是异步的,setPage 后马上使用 page 可能拿不到最新值。

建议把 fetchData 放到 setPage 的回调里,确保拿到最新页码:

useEffect(() => {
const observer = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting && !loading) {
setPage(prevPage => {
const nextPage = prevPage + 1;
fetchData(nextPage);
return nextPage;
});
}
});
if (bottomRef.current) observer.observe(bottomRef.current);
return () => observer.disconnect();
}, [loading]);


另外检查下后端 API 调用,确认分页逻辑没问题。有时数据库索引或查询条件不对也会导致数据重复。如果用 MySQL,记得给排序字段加索引,比如 ORDER BY created_at 这种。

再看看 API 返回的数据结构,最好带上当前页码和总页数这些信息,前端可以根据这些做判断,避免重复加载。
点赞
2026-03-31 12:00