React中useState与useEffect实现计时器的重复提交问题
问题分析与解决方案
核心问题:闭包陷阱导致的状态捕获异常
你的问题根源在于React闭包特性:
useEffect首次执行时,decTimer捕获的是组件初始渲染时的sent值(false),后续即使手动点击提交将sent设为true,旧闭包里的sent依然是初始值,导致计时器到点仍会触发sendAnswer。- 自动调用
sendAnswer时发送默认值,也是因为旧闭包捕获的输入状态是初始值,而非用户更新后的最新值。
修复方案
1. 用 useRef 持久化定时器ID
替换原有的 let timerInterval,使用 useRef 存储定时器ID,避免组件重渲染时丢失定时器引用:
const timerIntervalRef = useRef(null);
2. 更新 useEffect 依赖与定时器逻辑
将 sent 加入依赖数组,确保 decTimer 能捕获到最新的 sent 状态;同时在 sent 变为 true 时立即清除定时器,停止倒计时:
useEffect(() => { // 如果已提交,直接清除定时器 if (sent) { if (timerIntervalRef.current) { clearInterval(timerIntervalRef.current); timerIntervalRef.current = null; } return; } const decTimer = () => { setTimerTime((oldTimerTime) => { if (oldTimerTime === 1) { if (!sent) { sendAnswer(); } } return oldTimerTime - 1; }); }; // 监听SSE事件启动定时器(注意:避免重复绑定事件,可考虑在组件挂载时绑定一次) const handleGameEvent = (event) => { // 重置计时器初始值 setTimerTime(30); // 先清除旧定时器再启动新的 if (timerIntervalRef.current) { clearInterval(timerIntervalRef.current); } timerIntervalRef.current = setInterval(decTimer, 1000); }; sharedEventSource.addEventListener("game", handleGameEvent); // 组件卸载或依赖变化时清理 return () => { sharedEventSource.removeEventListener("game", handleGameEvent); if (timerIntervalRef.current) { clearInterval(timerIntervalRef.current); } }; }, [sharedEventSource, sent]); // 加入sent作为依赖
3. 确保 sendAnswer 使用最新状态
如果你的输入内容是通过 useState 管理的(比如 const [answer, setAnswer] = useState('')),直接在 sendAnswer 中使用 answer 即可,因为组件每次渲染都会重新创建 sendAnswer 函数,它会捕获最新的 answer 状态:
const sendAnswer = async () => { // 直接使用最新的answer状态 await fetch("......", { method: "POST", body: JSON.stringify({ answer }), // 其他配置... }); setSent(true); };
4. 优化:手动提交时立即清除定时器
在 sendAnswer 中主动清除定时器,避免倒计时继续执行:
const sendAnswer = async () => { // 清除定时器 if (timerIntervalRef.current) { clearInterval(timerIntervalRef.current); timerIntervalRef.current = null; } await fetch("......", {/*...*/}); setSent(true); };
关键注意点
- 始终在组件卸载或依赖变化时清理定时器和SSE事件监听,防止内存泄漏。
- 避免重复绑定SSE事件,若
sharedEventSource是全局实例,建议在组件挂载时仅绑定一次事件,而非每次依赖变化都绑定。
内容的提问来源于stack exchange,提问作者Crih.exe
相关产品推荐
相关产品推荐

