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

TS/React函数组件useEffect中fetch挂载时多次触发问题

请求重复触发的核心原因
  • React 18 开发环境默认开启的**StrictMode(严格模式)**会主动模拟「组件挂载-卸载-重新挂载」的生命周期流程,用来帮助开发者发现未做清理的副作用。在这个流程下,空依赖的useEffect会被连续执行两次,对应发出两次数据请求,这是开发环境的专属行为,生产环境不会触发。
  • 你当前的代码存在逻辑错位问题,是导致第三次请求触发的核心原因:
    1. 你在useEffect中调用异步的getData方法后,立刻同步判断if (data.length > 0),但这个判断读取的是组件挂载时的初始空状态,永远不会满足判断条件,根本无法进入数据转换的分支。
    2. 因为缺少请求状态锁、依赖数组的错误配置(比如调试时误将tableReady、data状态加入useEffect依赖列表),当异步请求返回触发setData更新状态时,useEffect会因为依赖变化再次执行,触发第三次请求。
    3. 你没有做组件卸载时的请求保护,前一次未完成的请求回调依然会触发状态更新,进一步放大请求重复的问题。
针对性修复方案
  • 移除不必要的中间状态:不需要单独存储data、tableReady这两个状态,拉取接口返回值后可以直接转换为表格需要的rows格式。
  • 给useEffect加上组件挂载状态标记,避免重复挂载、组件卸载时的无效状态更新和请求触发。
  • 修正后的核心实现逻辑参考:
useEffect(() => {
  let isComponentMounted = true;
  const fetchTableData = async () => {
    try {
      const currentUser = await Amplify.Auth.currentAuthenticatedUser();
      const token = currentUser.signInUserSession.idToken.jwtToken;
      const apiUrl = 'xxx';
      
      const response = await fetch(apiUrl, {
        method: 'GET',
        headers: { 'Authorization': token }
      });
      const result = await response.json();

      if (isComponentMounted) {
        // 直接将接口返回值转换为表格需要的行数据
        const tableRows = result.map(item => {
          const numericId = Number(item.id);
          return createData(numericId, item.user);
        });
        setRows(tableRows);
      }
    } catch (error) {
      console.log('数据拉取失败', error);
    }
  };

  fetchTableData();

  // 清理副作用:组件卸载或effect重新执行时,将挂载标记设为false
  return () => {
    isComponentMounted = false;
  };
}, []);
  • 验证点:修复后开发环境下如果依然出现两次请求,属于StrictMode的正常开发行为,打包到生产环境后只会触发一次请求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.30 10:36:10