React使用react-idle-timer实现会话超时模态框后无法重置超时时间问题
问题修复方案
核心原因
- 初始30秒超时的全局变量被
setTimeout的返回值(定时器ID)覆盖,导致传入IdleTimer组件的超时参数错误,后续计时规则混乱 - 点击「继续会话」后仅清除了自定义的倒计时定时器,没有调用IdleTimer实例自带的重置方法,原有闲置计时没有被重置
修改后的完整代码
import React, { useState, useRef } from "react"; import IdleTimer from "react-idle-timer"; import { useDispatch } from "react-redux"; import { bindActionCreators } from "redux"; import { actionCreators } from '../state/index'; import { useHistory } from "react-router-dom"; import { useSelector } from "react-redux"; import SessionTimeoutDialog from './SessionTimeoutDialog'; let countdownInterval; // 常量存储初始闲置超时时间,避免被覆盖 const IDLE_TIMEOUT = 1000 * 30 * 1; // 单独变量存储弹窗触发定时器 let idlePopupTimer; const SessionTimeout = () => { const idleTimer = useRef(null); const history = useHistory(); const login = useSelector((state) => state.login); // 用于判断用户是否登录 const dispatch = useDispatch(); const { logout } = bindActionCreators(actionCreators, dispatch); // 登出方法 const [timeoutModalOpen, setTimeoutModalOpen] = useState(false); const [timeoutCountdown, setTimeoutCountdown] = useState(0); const onActive = () => { // 计时器自动重置 if (!timeoutModalOpen) { clearSessionInterval(); clearSessionTimeout(); } }; const onIdle = () => { const delay = 1000 * 5; if(login.logged && !timeoutModalOpen) { // 赋值给单独的变量,不覆盖初始超时配置 idlePopupTimer = setTimeout(() => { let countDown = 60; setTimeoutModalOpen(true); setTimeoutCountdown(countDown); countdownInterval = setInterval(() => { if (countDown > 0) { setTimeoutCountdown(--countDown); } else { handleLogout(); } }, 1000); }, delay); } }; const clearSessionTimeout = () => { clearTimeout(idlePopupTimer); }; const clearSessionInterval = () => { clearInterval(countdownInterval); }; const handleLogout = () => { setTimeoutModalOpen(false); clearSessionInterval(); clearSessionTimeout(); logout(); history.push("/login"); }; const handleContinue = () => { setTimeoutModalOpen(false); clearSessionInterval(); clearSessionTimeout(); // 调用IdleTimer实例的reset方法,重置计时为初始30秒 idleTimer.current.reset(); }; return ( <> <IdleTimer ref={idleTimer} onActive={onActive} onIdle={onIdle} debounce={250} timeout={IDLE_TIMEOUT} /> <SessionTimeoutDialog countdown={timeoutCountdown} onContinue={handleContinue} onLogout={handleLogout} open={timeoutModalOpen} /> </> ); }; export default SessionTimeout;
额外优化建议
全局变量countdownInterval和idlePopupTimer建议改为用useRef存储,避免多实例场景下变量互相干扰。
内容的提问来源于stack exchange,提问作者myTest532 myTest532
相关产品推荐
相关产品推荐

