You need to enable JavaScript to run this app. React使用react-idle-timer实现会话超时模态框后无法重置超时时间问题
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.18 23:15:08