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

React从状态/Hook取数后发起异步调用触发无限循环如何解决

问题根因

你的判断完全准确,无限循环的触发链路是:

  1. 组件重渲染时,useFarmInfo、useDualFarmInfo每次都会返回全新引用的对象/数组,即使内容和上一次渲染完全一致
  2. 引用变化导致useMemo判定依赖更新,重新生成新的pairLists数组
  3. pairLists引用变化触发useEffect执行,调用接口后setBulkPairs更新状态,再次触发组件重渲染,回到第一步形成死循环

另外注意:useMemo仅适合同步计算值缓存,异步请求属于副作用,不能放在useMemo中执行,会引发渲染时序异常。

修复步骤

1. 先修复自定义Hook返回值引用不稳定的问题(核心修复)

给自定义Hook的返回值加缓存,保证内容不变时引用不发生变化:

export function useFarmInfo(): {
  [chainId in ChainId]: StakingBasic[];
} {
  const defaultFarms = useDefaultFarmList();
  // 缓存对应链的农场数组,仅当源数据变化时重新生成
  const maticFarms = useMemo(
    () => Object.values(defaultFarms[ChainId.MATIC]),
    [defaultFarms]
  );
  // 缓存整个返回对象,避免每次渲染生成新对象引用
  return useMemo(
    () => ({
      [ChainId.MATIC]: maticFarms,
      [ChainId.MUMBAI]: [],
    }),
    [maticFarms]
  );
}

useDualFarmInfo按照同样的逻辑,给内部生成的数组、返回的外层对象加useMemo缓存即可。

2. 优化pairLists的依赖范围

不要把整个农场对象作为依赖,只取当前链实际用到的农场列表作为依赖,减少不必要的更新触发:

// 直接取当前链对应的农场列表,不持有整个对象的依赖
const currentLpFarms = lpFarms[chainIdOrDefault];
const currentDualFarms = dualFarms[chainIdOrDefault];

const pairLists = useMemo(() => {
  const stakingPairLists = currentLpFarms.map((item) => item.pair);
  const dualPairLists = currentDualFarms.map((item) => item.pair);
  return stakingPairLists.concat(dualPairLists);
}, [chainIdOrDefault, currentLpFarms, currentDualFarms]);

3. 给异步请求加过期守卫,避免无效更新

就算引用完全稳定,也建议给useEffect里的异步逻辑加竞态处理,避免组件卸载、请求过期后错误更新状态:

useEffect(() => {
  // 标记当前请求是否有效
  let isActive = true;

  // 空列表直接跳过请求,重置状态即可
  if (pairLists.length === 0) {
    setBulkPairs({});
    return () => { isActive = false; };
  }

  getBulkPairData(pairLists).then((data) => {
    // 仅当请求有效时才更新状态
    if (isActive) {
      setBulkPairs(data);
    }
  });

  // 卸载或依赖更新时标记当前请求失效
  return () => {
    isActive = false;
  };
}, [pairLists]);
额外优化建议

如果接口返回的数据结构稳定,可以在setBulkPairs前加一层关键字段对比或者深比较,如果返回数据和现有状态完全一致就不触发setState,进一步减少多余重渲染。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 07:27:17