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

React中如何解决自定义Hook函数引发的useEffect无限循环问题?

问题原因及解决方案

无限循环的核心原因

  • 自定义Hook返回的对象引用不稳定:useCustomHook每次执行时,都会创建一个全新的{ func }对象。组件每次渲染调用useCustomHook(),得到的customHook都是新的引用。
  • 依赖数组触发回调重创建:handleFunc的依赖数组包含customHook,所以每次customHook引用变化,handleFunc都会被重新定义。
  • useEffect的依赖更新触发重复执行:useEffect监听handleFunc,每次handleFunc更新就会调用它;而handleFunc里的mutateAsync如果触发了组件状态/缓存更新(这是useMutation的常见行为),会导致组件重新渲染,进而再次触发整个循环,形成无限调用。

修复方案

方案1:让自定义Hook返回的函数引用稳定

修改useCustomHook,用useCallback包裹func,确保其引用在依赖不变时保持稳定:

import { useCallback } from 'react';

const useCustomHook = () => {
  const func = useCallback(() => {
    // ...doSomething
  }, []); // 这里根据实际逻辑添加func的依赖项

  return {
    func,
  };
};

export default useCustomHook;

方案2:调整handleFunc的依赖,直接依赖func而非整个对象

如果不想修改自定义Hook,可以在handleFunc的依赖里直接声明customHook.func,而非整个customHook对象:

const handleFunc = useCallback(async () => {
  if (!router.isReady) {
    return;
  }

  try {
    await mutateAsync();
    customHook.func();
  } catch (error) {
  }
}, [
  mutateAsync,
  router.isReady,
  customHook.func, // 改为依赖func本身,而非整个对象
]);

方案3:限制useEffect的触发次数(仅挂载时执行)

如果handleFunc只需要在组件挂载时执行一次,可以将useEffect的依赖设为空数组,同时用useRef避免闭包过期问题:

const handleFuncRef = useRef(handleFunc);
useEffect(() => {
  handleFuncRef.current = handleFunc;
}, [handleFunc]);

useEffect(() => {
  handleFuncRef.current();
}, []); // 空数组仅在组件挂载时执行一次

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 12:47:16