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

React useEffect致/api/checkCookie接口重复调用4次问题排查

问题分析与解决方案

核心问题

API请求被触发4次,主要由以下原因导致:

  1. 自定义Hook错误标记为async
    React Hook必须是同步函数,给useCheckCookieToken加上async关键字会破坏Hook执行规则,引发组件渲染逻辑异常,可能导致副作用重复执行。

  2. React Strict Mode的开发环境行为
    开发模式下,React Strict Mode会主动触发两次组件挂载/卸载流程(执行useEffect后立即调用清理函数,再重新执行useEffect),用于检测副作用泄漏。如果TableComp被渲染两次,就会出现4次API请求。

  3. 状态初始值未明确设置
    useState()初始值为undefined,导致组件首次渲染时session !== null为true,直接渲染子组件;fetch完成后setSession又触发一次重渲染,增加了不必要的渲染周期。

修复步骤

1. 移除自定义Hook的async关键字

Hook本身不能是异步函数,修改后的代码如下:

function useCheckCookieToken() {
  const [session, setSession] = useState(null); // 明确初始值为null

  useEffect(() => {
    const controller = new AbortController(); // 添加请求取消控制器
    const signal = controller.signal;

    async function sessionPost() {
      try {
        const res = await fetch(`/api/checkCookie`, {
          method: 'GET',
          headers: {
            'Content-Type': 'application/json'
          },
          signal // 绑定取消信号
        });
        if (res.ok) {
          const result = await res.json();
          setSession(result);
        } else {
          setSession(null); // 请求失败时重置状态
        }
      } catch (err) {
        if (err.name !== 'AbortError') {
          console.error('请求失败:', err);
          setSession(null);
        }
      }
    }

    sessionPost();

    return () => {
      controller.abort(); // 组件卸载时取消请求
      console.log('unmount');
    };
  }, []);

  return session;
}

module.exports = {
  useCheckCookieToken
};

2. 处理Strict Mode的重复请求(可选)

开发环境下Strict Mode的两次执行是正常现象,生产环境会自动消失。如果想在开发环境避免重复请求,可以添加请求锁:

function useCheckCookieToken() {
  const [session, setSession] = useState(null);
  const isRequested = useRef(false); // 标记是否已发起请求

  useEffect(() => {
    if (isRequested.current) return;
    isRequested.current = true;

    const controller = new AbortController();
    const signal = controller.signal;

    async function sessionPost() {
      // 原有请求逻辑
    }

    sessionPost();

    return () => {
      controller.abort();
      isRequested.current = false; // 卸载时重置标记
      console.log('unmount');
    };
  }, []);

  return session;
}

3. 检查组件挂载次数

确认TableComp是否被父组件多次渲染,比如路由配置错误、条件渲染逻辑重复等。可以在组件中添加日志排查:

function TableComp() {
  const session = useCheckCookieToken();
  console.log('TableComp渲染'); // 查看渲染次数

  return (
    session !== null ?
      <>
        <Menu />
        <AddService />
        <DataTable />
      </>
      :
      <Navigate to="/" />
  );
}

验证

修复后,开发环境下Strict Mode会触发2次请求(生产环境1次)。如果仍出现4次请求,需检查是否有多个组件实例调用了useCheckCookieToken,或父组件存在不必要的重渲染导致TableComp多次挂载。

内容的提问来源于stack exchange,提问作者XAZG Неизвестный

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 17:20:42