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

React TypeScript:阻止状态变化引发API多次调用

解决API重复调用的问题

你的问题核心在于直接在组件渲染逻辑里调用了API函数——每次组件因为父状态变化触发重新渲染时,if (confirmationCode)这个判断都会执行checkConfirmationCode,自然就导致了多次API请求。

要实现仅调用一次的需求,我们可以借助React的useEffect钩子来精准控制API的执行时机,具体调整方案如下:

步骤1:将API调用移至useEffect

useEffect专门用来处理组件的副作用操作(比如API请求),能帮我们控制代码的执行时机。注意:useEffect的回调不能直接是async函数,需要在内部定义异步函数或者立即执行匿名异步函数。

步骤2:设置精准的依赖数组

为了确保只有在必要时才触发API调用,我们需要把confirmationCode和global.apiUrl加入依赖数组——只有当这两个值发生变化时,才重新执行请求,避免父组件状态变化导致的无意义重复调用。

步骤3:添加请求取消逻辑(可选但推荐)

为了避免组件卸载时还在进行的请求导致内存泄漏,我们可以用AbortController来取消未完成的请求。

修改后的完整代码

import React, {useContext, useEffect} from 'react';
import Context from '../components/context';
import {RouteComponentProps} from 'react-router-dom';

interface MyProps {
  confirmationCode: string,
}

const Confirm: React.FC<RouteComponentProps<MyProps>> = (props) => {
  const { global } = useContext(Context) as {global: any};
  const confirmationCode = props.match.params.confirmationCode;

  async function checkConfirmationCode(controller: AbortController) {
    try {
      const response = await fetch(`${global.apiUrl}/user/confirm_email`, {
        method: 'POST',
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({confirmationCode}),
        signal: controller.signal // 绑定取消信号
      });

      if (response.status === 200) {
        localStorage.setItem("warning", 'confirmed');
      } else if (response.status === 400) {
        localStorage.setItem("warning", 'invalid');
      }
    } catch (error) {
      // 处理请求被取消的情况
      if (error instanceof DOMException && error.name === 'AbortError') {
        console.log('请求已取消');
      } else {
        console.error('请求出错:', error);
      }
    }
  }

  useEffect(() => {
    const controller = new AbortController();
    
    if (confirmationCode) {
      checkConfirmationCode(controller);
    }

    // 组件卸载时取消未完成的请求
    return () => controller.abort();
  }, [confirmationCode, global.apiUrl]); // 依赖数组:仅当这两个值变化时才执行

  return (
    <div>test</div>
  );
}

export default Confirm;

关键说明

  • 现在API请求只会在组件首次挂载(且confirmationCode存在),或者confirmationCode/global.apiUrl变化时执行,彻底避免了父组件状态变化导致的重复调用。
  • AbortController的加入确保了组件卸载时能终止未完成的请求,防止潜在的内存泄漏问题。
  • 依赖数组要精准:如果你的global对象有其他影响请求的属性,建议解构出具体属性(比如const { apiUrl } = global)再加入依赖,避免不必要的重执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:33:27