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

自定义React Hook返回值引发useEffect无限循环问题求助

解决useCountries Hook引发useEffect无限循环的问题

问题根源

每次组件重渲染时,useCountries里通过concat生成的combinedCountries都是新数组实例——哪怕数组内容完全没变,React的依赖对比机制也会判定它是新值,导致依赖数组包含countries的useEffect反复执行,形成无限循环。

最优解决方案:在Hook内部缓存数组

直接修改useCountries,用useMemo缓存合并后的数组,确保只有当原始国家数据变化时,才生成新数组:

export function useCountries() {
  const { data: countryData, isLoading } = useQuery<ICountries, string>(["countries"], () => fetchCountries(), {
    refetchOnWindowFocus: false,
    onError: (err) => {
      error("Could not get countries!, " + err);
    },
  });

  // 用useMemo缓存合并结果,依赖原始数据字段
  const combinedCountries = useMemo(() => {
    return (countryData?.prioritizedCountries || []).concat(countryData?.countries || []);
  }, [countryData?.prioritizedCountries, countryData?.countries]);

  return {
    countries: combinedCountries,
    isFetchingCountries: isLoading,
  };
}

这样只要countryData里的prioritizedCountries和countries内容不变,返回的countries数组引用就不会变,useEffect就不会无故触发。

额外排查点

如果修改后仍有循环,检查useEffect里的setSettingsFromCountryChange是否会更新settings:

  • 如果这个方法会修改settings,那么settings变化又会触发useEffect,形成新的循环
  • 此时可以在调用setSettingsFromCountryChange前加判断,只有当目标内容和当前settings不一致时才执行:
const countryInfo = countries.find((country) => country.id === settings?.treatmentCountryGuid);
if (countryInfo && settings?.legalDepartmentGuid && settings?.defaultLanguage) {
  // 对比关键字段,避免不必要的更新
  if (settings.treatmentCountryGuid !== countryInfo.id) {
    setSettingsFromCountryChange(countryInfo);
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 20:09:24