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

如何在Promise的then回调中修改React state避免触发报错

报错原因

该报错的核心触发逻辑是:emailjs.sendForm 是异步请求,当请求完成执行 then 回调时,调用提交函数的组件可能已经从页面卸载,此时对已卸载组件执行状态更新操作,就会触发React的报错。

修复方案

方案1:用useRef跟踪组件挂载状态(全版本兼容)

通过ref标记组件的挂载状态,仅在组件仍挂载时执行状态更新操作:

import { useRef, useEffect } from 'react'

// 组件内部代码
const isMounted = useRef(true)

useEffect(() => {
  // 组件卸载时更新标记
  return () => isMounted.current = false
}, [])

const submitEmail = () => {
    emailjs
      .sendForm(
        "你的serviceID",
        "你的templateID",
        data.current,
        "你的publicKey"
      )
      .then(
        (res) => {
          props.setReady(true);
          // 新增挂载状态判断
          if (isMounted.current) {
            setStatusMailJS("Письмо отправлено");
          }
        },
        (error) => {
          props.setReady(true);
        }
      );
  };

方案2:用AbortController取消未完成请求(React 18+ 推荐)

如果使用的是emailjs v3及以上版本,可以通过传入信号量,在组件卸载时直接取消未完成的异步请求,从根源避免回调执行:

import { useEffect, useState } from 'react'

// 组件内部代码
const [abortController, setAbortController] = useState(null)

useEffect(() => {
  // 组件卸载时取消未完成的请求
  return () => abortController?.abort()
}, [abortController])

const submitEmail = () => {
    const controller = new AbortController()
    setAbortController(controller)

    emailjs
      .sendForm(
        "你的serviceID",
        "你的templateID",
        data.current,
        "你的publicKey",
        { signal: controller.signal }
      )
      .then(
        (res) => {
          props.setReady(true);
          setStatusMailJS("Письмо отправлено");
        },
        (error) => {
          // 忽略请求取消的报错
          if (error.type !== 'abort') {
            props.setReady(true);
          }
        }
      );
  };

其他排查点

如果按上述方案修改后仍报错,需要检查setStatusMailJS是否是useState正确返回的状态修改函数,确认没有拼写错误、作用域引用错误的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 23:06:00