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

React中单个无限滚动内两个useSwrInfinite钩子仅一个触发问题

问题:同一个自定义Hook中多个useSwrInfinite仅第一个触发请求

我需要构建一个无限滚动组件,从两个不同的分页数据源渲染卡片。加载逻辑是:用户滚动加载更多时,优先请求第一个数据源的下一页;当第一个数据源没有更多结果时,再请求第二个数据源的下一页。

为此我在同一个自定义Hook中两次调用useSwrInfinite,代码如下:

const useInfiniteFetchAlphasAndBetas = () => {
   const alphaData = useSwrInfinite( ... FETCH_ALPHAS_URL)
   const betaData = useSwrInfinite( ... FETCH_BETAS_URL)

   const hasMoreAlphaResults = alphaData?.length ? alphaData[alphaData.length - 1].pageInfo?.hasNextPage : false
   const hasMoreBetaResults = betaData?.length ? betaData[betaData.length - 1].pageInfo?.hasNextPage : false

   const hasMoreResults = hasMoreAlphaResults || hasMoreBetaResults

   const handleLoadMoreItems = () => {
     if(hasMoreAlphaResults) alphaData.setSize(alphaData.size + 1)
     else if(hasMoreBetaResults) betaData.setSize(betaData.size + 1)
   }

   return { alphaData, betaData, hasMoreResults, handleLoadMoreItems}
}

但实际运行时发现:只有第一个调用的useSwrInfinite钩子会发起请求,第二个完全不触发;如果调换两个钩子的调用顺序,原来的第一个钩子就不再触发请求。请问是否无法在同一个自定义Hook中同时调用多个useSwrInfinite?


解决方案

这是因为useSwrInfinite的内部状态管理依赖于钩子的调用顺序和独立的实例上下文,当你在同一个自定义Hook中连续调用两个useSwrInfinite时,它们的内部状态(比如size)会互相干扰,导致只有第一个钩子能正常触发请求更新。

解决方法是将两个无限请求逻辑分开封装到独立的自定义Hook中,避免状态冲突:

// 单独封装第一个数据源的无限请求逻辑
const useInfiniteAlphas = () => {
  const alphaData = useSwrInfinite(
    (pageIndex, previousPageData) => {
      // 生成alpha数据源的分页请求key
      if (previousPageData && !previousPageData.pageInfo.hasNextPage) return null;
      return `${FETCH_ALPHAS_URL}?page=${pageIndex + 1}`;
    },
    { revalidateFirstPage: false }
  );

  const hasMore = alphaData.data?.length 
    ? alphaData.data[alphaData.data.length - 1].pageInfo?.hasNextPage 
    : false;

  return { ...alphaData, hasMore };
};

// 单独封装第二个数据源的无限请求逻辑
const useInfiniteBetas = () => {
  const betaData = useSwrInfinite(
    (pageIndex, previousPageData) => {
      // 生成beta数据源的分页请求key
      if (previousPageData && !previousPageData.pageInfo.hasNextPage) return null;
      return `${FETCH_BETAS_URL}?page=${pageIndex + 1}`;
    },
    { revalidateFirstPage: false }
  );

  const hasMore = betaData.data?.length 
    ? betaData.data[betaData.data.length - 1].pageInfo?.hasNextPage 
    : false;

  return { ...betaData, hasMore };
};

// 整合两个Hook的加载逻辑
const useInfiniteFetchAlphasAndBetas = () => {
  const alpha = useInfiniteAlphas();
  const beta = useInfiniteBetas();

  const hasMoreResults = alpha.hasMore || beta.hasMore;

  const handleLoadMoreItems = () => {
    if (alpha.hasMore) {
      alpha.setSize(alpha.size + 1);
    } else if (beta.hasMore) {
      beta.setSize(beta.size + 1);
    }
  };

  return { alphaData: alpha, betaData: beta, hasMoreResults, handleLoadMoreItems };
};

原理说明

useSwrInfinite每个实例都会维护自己的size、data等内部状态,分开封装后,两个钩子的状态完全独立,不会互相干扰。在整合的Hook中,我们只需要根据各自的hasMore状态来触发对应的加载逻辑即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 07:52:50