React中邮件发送函数重复执行及console.log多次输出问题求助
解决邮件重复发送与console.log重复输出问题
我正在开发一个根据过期日期发送邮件的函数,测试时功能正常,但邮件会重复发送,且console.log会多次输出。请问该如何解决?
**注意:**我知道当前函数会在未到过期日期时发送邮件,我只想修复console.log重复输出的问题。
当前代码片段
if (product?.expiry) { var arr = [] var today = new Date() var expiry = new Date(product?.expiry) var week = new Date(expiry.setDate(expiry.getDate() - 7)) var template = { message: product.name + " is reaching expiry date", footer: "Expiry Date: " + week.toDateString() } const interval = setInterval(() => { if (arr.length > 0) { clearInterval(interval) console.log(arr) } if (today !== expiry) { // actual emailing emailjs.send(SERVICE_API, TEMPLATE_API, template, PUBLIC_API) .then(function(response) { console.log('SUCCESS!', response.status, response.text); }, function(error) { console.log('FAILED...', error) }); arr.push('found') } }, 1000) }
函数剩余部分
const expiryEmail = () => { if (today !== week) { emailjs.send(SERVICE_API, TEMPLATE_API, template, PUBLIC_API) .then(function(response) { console.log('SUCCESS!', response.status, response.text); }, function(error) { console.log('FAILED...', error) }); } } setTimeout(() => { }) useEffect(() => { if (!product) { return; } //problem is that the condition returns null first time around expiryEmail() },[])
解决方案
核心问题分析
setInterval每秒执行一次,清除定时器后未终止后续代码,导致仍会触发邮件发送和日志输出useEffect未处理组件卸载时的定时器清理,可能导致内存泄漏和重复执行- Date对象直接用
!==比较是引用比较,逻辑错误且可能触发不必要的执行 - 无状态标记,无法控制
expiryEmail只执行一次
修改步骤
1. 添加发送状态标记,避免重复执行
用useRef记录邮件是否已发送,确保expiryEmail只触发一次:
import { useEffect, useRef } from 'react'; // ...其他代码 const expiryEmail = () => { // 转换日期为当天0点的时间戳,避免时分秒干扰比较 const todayTimestamp = new Date().setHours(0, 0, 0, 0); const weekTimestamp = new Date(product.expiry).setDate(new Date(product.expiry).getDate() - 7).setHours(0, 0, 0, 0); if (todayTimestamp !== weekTimestamp) { emailjs.send(SERVICE_API, TEMPLATE_API, template, PUBLIC_API) .then(response => console.log('SUCCESS!', response.status, response.text)) .catch(error => console.log('FAILED...', error)); } } useEffect(() => { if (!product) return; const hasSent = useRef(false); if (!hasSent.current) { expiryEmail(); hasSent.current = true; } // ...定时器逻辑(如果需要保留的话) }, [product]);
2. 修复定时器逻辑,清除后终止执行
如果必须保留setInterval,修改后确保清除定时器后不再执行后续代码:
const interval = setInterval(() => { if (arr.length > 0) { clearInterval(interval); console.log(arr); return; // 清除后直接返回,避免触发邮件发送 } // 改用时间戳比较日期 const todayTimestamp = today.setHours(0, 0, 0, 0); const expiryTimestamp = expiry.setHours(0, 0, 0, 0); if (todayTimestamp !== expiryTimestamp) { emailjs.send(SERVICE_API, TEMPLATE_API, template, PUBLIC_API) .then(res => console.log('SUCCESS!', res.status, res.text)) .catch(err => console.log('FAILED...', err)); arr.push('found'); } }, 1000);
3. 清理定时器,避免内存泄漏
在useEffect的返回函数中清除定时器,防止组件卸载后定时器继续运行:
useEffect(() => { let interval; if (product?.expiry) { // ...定时器初始化逻辑 } // 组件卸载时清除定时器 return () => { if (interval) clearInterval(interval); }; }, [product]);
内容的提问来源于stack exchange,提问作者ryand123
相关产品推荐
相关产品推荐

