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

如何在useEffect中追踪对象引用?解决deps依赖无限循环问题

React 自定义API Hook依赖项无限循环问题解决

问题场景

在构建useReader自定义API Hook时,期望传入的deps数组内容变化时触发useEffect重新执行数据请求,但目前无论直接使用deps、[deps ?? []]还是展开deps的写法,都引发了无限循环。deps支持undefined或any[]类型。

Hook实现代码

export const useReader = <TResponseData>({ url, deps, options }: TypeUseReader<TResponseData>) => {
    const [data, setData] = useState<TResponseData | null>(null);
    const [isLoading, setIsLoading] = useState<boolean>(false);
    const [error, setError] = useState<number | null >(null);

    async function fetchData(newUrl?: string) {}

    useEffect(() => {
       // ..fetch逻辑
    // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [url, deps]); // 此处deps导致无限循环

    return {
        data,
        isLoading,
        error,
        fetchData
    };
};

Hook使用方式

return useReader<FOO>({
    url: 'URL_PLACEHOLDER',
    deps: [anything] /* FIXME: deps引发无限循环 */
});

问题原因

React的useEffect依赖项通过浅比较判断是否变化:

  • 若调用useReader时直接传入deps: [anything],每次组件渲染都会生成一个新的数组引用,React会认为依赖项发生变化,触发useEffect重新执行,进而导致组件重新渲染,形成循环。
  • 直接将deps数组作为依赖项时,React比较的是数组的引用而非内部元素,只要引用变化就会触发回调。

解决方案

方案1:在Hook内部展开deps元素作为依赖

修改useEffect的依赖数组,将deps的元素逐个加入依赖,而非使用数组本身:

useEffect(() => {
   // ..fetch逻辑
}, [url, ...(deps ?? [])]);

这样React会直接比较deps数组中的每个元素,而非数组引用。但需注意:若deps中包含引用类型元素(如对象、数组),仍需确保这些元素的引用稳定,否则仍可能引发循环。

方案2:外部传入稳定的deps引用

在调用useReader的组件中,用useMemo包裹deps数组,确保只有内部元素变化时才更新数组引用:

const stableDeps = useMemo(() => [anything], [anything]);
return useReader<FOO>({
    url: 'URL_PLACEHOLDER',
    deps: stableDeps
});

这种方式从根源上保证了deps引用的稳定性,避免因数组重复创建导致的不必要触发。

额外优化:稳定fetchData函数

原代码中fetchData函数每次渲染都会重新创建,即使添加了eslint忽略,也可能引发潜在问题。可以用useCallback包裹fetchData,并补充完整依赖:

const fetchData = useCallback(async (newUrl?: string) => {
    // ..fetch逻辑
}, [/* 此处添加fetchData用到的依赖,如setData、setIsLoading等 */]);

然后在useEffect中使用这个稳定的函数,并移除eslint忽略注释。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 22:47:32