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

React实现带搜索的无限滚动 清空搜索后分页失效处理

问题根因

分页失效的核心问题有3个:

  • 搜索关键词变更时,仅重新拉取了第一页数据,没有同步重置page页码状态和hasMore加载标记:搜索过程中不断累加的页码,会在清空搜索后直接作为请求参数传给接口,导致跳过正常的分页顺序,拿不到对应数据
  • 分页加载逻辑直接取闭包中缓存的page、data旧值,快速滚动或者状态快速变更时容易出现数据拼接错误、页码跳变
  • 原代码中JSX部分漏写了data.map的数据源变量,会直接导致渲染报错(属于笔误)
修复方案
  • 在监听search变化的副作用逻辑中,每次重新拉取第一页数据后,将page重置为1(因为第一页page=0已经加载完成,下一次触发加载要请求第1页),同时将hasMore重置为true,保证后续滚动可以正常触发加载
  • 调整分页请求和状态更新逻辑,用React状态的函数式更新获取最新的状态值,避免闭包旧值导致的逻辑错误
  • 补全JSX中缺失的data数据源遍历逻辑,可选优化:对搜索参数做URL编码,避免特殊字符导致请求异常
修复后完整代码
useEffect(() => {
  const getData = async () => {
    const { data } = await axios(
      search
        ? `http://localhost:3003/api/product/pagination?page=0&search=${encodeURIComponent(search)}`
        : `http://localhost:3003/api/product/pagination?page=0`
    );

    setData(data.posts);
    // 重置分页状态
    setPage(1);
    setHasMore(true);
  };

  if (search.length === 0 || search.length > 2) {
    getData();
  }
}, [search]);

const fetchPosts = async (currentPage, searchKey) => {
  const { data } = await axios(
    `http://localhost:3003/api/product/pagination?page=${currentPage}&search=${encodeURIComponent(searchKey)}`
  );
  return data.posts;
};

const fetchData = async () => {
  setPage(prevPage => {
    // 用最新的页码值发起请求
    fetchPosts(prevPage, search).then(postsFromServer => {
      setData(prevData => [...prevData, ...postsFromServer]);
      if (postsFromServer.length === 0 || postsFromServer.length < 4) {
        setHasMore(false);
      }
    });
    return prevPage + 1;
  });
};

return (
  <>
    <InfiniteScroll
      dataLength={data.length}
      next={fetchData}
      hasMore={hasMore}
      loader={<h4>Loading...</h4>}
    >
      <Container>
        {data.map((item) => {
          const {
            _id,
            kampaniyaName,
            owner,
            aboutProduct,
            startDate,
            endDate,
            price,
            category,
            image,
          } = item;

          return (
            <div key={item._id}>
              <Card
                _id={_id}
                name={kampaniyaName}
                company={owner}
                about={aboutProduct}
                date={timeLeft(startDate, endDate)}
                price={price}
                category={category}
                image={image}
                data={item}
              />
            </div>
          );
        })}
      </Container>
    </InfiniteScroll>
  </>
);
};

export default Home;
额外优化建议
  • 可以加一个loading状态锁,避免滚动到临界点时重复触发相同页码的请求
  • 搜索输入建议加防抖,减少输入过程中无效的接口请求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 07:30:48