You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React InfiniteScroll组件加载异常无限渲染问题修复方案

react-infinite-scroll 加载异常、无限渲染问题修复

两个异常的核心原因

  • 写next={fetchDataOnScroll()}导致页面卡死:你传入的是函数立即执行的结果而非函数引用,组件每次渲染都会立刻执行请求,请求完成更新state触发重渲染,重渲染又再次执行请求,进入死循环。next属性必须传入函数引用本身,不能加调用括号。
  • 传函数引用时一直显示LOADING、无法加载内容:代码里存在3个直接阻断逻辑运行的bug:
    • 接口返回判断逻辑缺少if关键字,(res.data.doc.length === 0) setHasMore(false)属于非法语法,会直接中断fetch函数执行,请求后续的更新状态逻辑完全不会运行。
    • 存在闭包陷阱:fetch函数里直接读取外层的pageNumber状态,组件触发滚动加载时拿到的永远是初始页码1,每次请求都拉取第一页数据,页码更新不会同步到触发的加载函数中,导致加载逻辑紊乱。
    • 错误捕获逻辑的对象路径写反:axios报错的结构是error.response.data,你写的error.data.response会在请求出错时抛出二次错误,吞掉真实的报错信息,根本无法定位接口问题。

修复后可直接运行的代码

import { useState } from 'react'
import axios from 'axios'
import InfiniteScroll from 'react-infinite-scroll-component'
import FeedCard from './FeedCard'

export default function PostList() {
  const [posts, setPosts] = useState([])
  const [hasMore, setHasMore] = useState(true)
  const [pageNumber, setPageNumber] = useState(1)
  // 新增加载锁,防止重复触发请求
  const [loading, setLoading] = useState(false)

  const fetchDataOnScroll = async () => {
    // 加载中直接返回,避免重复请求
    if (loading) return
    try {
      setLoading(true)
      const res = await axios.get(
        `${process.env.REACT_APP_API}/api/v1/posts?page=${pageNumber}`
      )
      const newPosts = res.data.doc
      if (newPosts.length === 0) {
        setHasMore(false)
      } else {
        setPosts((prev) => [...prev, ...newPosts])
        setPageNumber((prev) => prev + 1)
      }
    } catch (error) {
      alert('Error fetching Posts')
      // 修正错误打印路径
      console.log('ERROR', error?.response?.data)
    } finally {
      setLoading(false)
    }
  }

  return (
    <InfiniteScroll
      hasMore={hasMore}
      next={fetchDataOnScroll}
      endMessage={<p style={{ textAlign: 'center' }}>No More Post</p>}
      dataLength={posts.length}
      loader={<h1>LOADING...</h1>}
    >
      {posts.map((post) => (
        <FeedCard key={post._id} post={post} />
      ))}
    </InfiniteScroll>
  )
}

额外注意事项

  • 如果你的列表是在固定高度的容器内滚动,不是全局window滚动,必须给InfiniteScroll组件添加scrollableTarget属性,传入滚动容器的id,否则组件找不到正确的滚动监听对象,会一直卡在加载状态。
  • 初始加载时如果posts为空导致容器高度不足,组件会自动触发第一次拉取,不需要额外在useEffect中手动调用fetch函数。
  • 接口返回的新数据长度如果小于你后端设置的单页条数,也要同步设置hasMore为false,避免后续无效触发。

内容的提问来源于stack exchange,提问作者merlin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 02:18:03