如何在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
相关产品推荐
相关产品推荐

