首页 > 解决方案 > React 中的会话超时与模态

问题描述

我第一次使用它创建了一个会话超时react-idle-timer,但当我在模式警告中单击“继续会话”时,它不会将超时重置为原始设置(本例中为 30 秒)。单击继续会话后,它会每 5 秒打开一次警告模式。

会话超时.js

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;
let timeout = 1000 * 30 * 1;

const SessionTimeout = () => {
    const idleTimer = useRef(null);
    const history = useHistory();

    const login = useSelector((state) => state.login);  // this is just to see if a user is logged
    const dispatch = useDispatch();
    const { logout } = bindActionCreators(actionCreators, dispatch); // this is to logout

    const [timeoutModalOpen, setTimeoutModalOpen] = useState(false);
    const [timeoutCountdown, setTimeoutCountdown] = useState(0);

    const onActive = () => {
        // timer reset automatically.
        if (!timeoutModalOpen) {
            clearSessionInterval();
            clearSessionTimeout();
        }
    };
    
    const onIdle = () => {
        const delay = 1000 * 5;
        if(login.logged && !timeoutModalOpen) {
            timeout = setTimeout(() => {
                let countDown = 60;
                setTimeoutModalOpen(true);
                setTimeoutCountdown(countDown);
                countdownInterval = setInterval(() => {
                  if (countDown > 0) {
                    setTimeoutCountdown(--countDown);
                  } else {
                    handleLogout();
                  }
                }, 1000);
            }, delay);
        }
    };

    const clearSessionTimeout = () => {
        clearTimeout(timeout);
    };
    
    const clearSessionInterval = () => {
        clearInterval(countdownInterval);
    };

    const handleLogout = () => {
        setTimeoutModalOpen(false);
        clearSessionInterval();
        clearSessionTimeout();
        logout();
        history.push("/login");
    };
      
    const handleContinue = () => {
        setTimeoutModalOpen(false);
        clearSessionInterval();
        clearSessionTimeout();
    };

    return (
        <>
          <IdleTimer
            ref={idleTimer}
            onActive={onActive}
            onIdle={onIdle}
            debounce={250}
            timeout={timeout}
          />
          <SessionTimeoutDialog
            countdown={timeoutCountdown}
            onContinue={handleContinue}
            onLogout={handleLogout}
            open={timeoutModalOpen}
          />
        </>
    );
};

export default SessionTimeout;

这是我的模式(对话框)。SessionTimeoutDialog.jsx

import React from "react";
import * as PropTypes from "prop-types";
import {
  Dialog,
  DialogTitle,
  DialogContent,
  DialogActions,
  Button,
  Typography,
  makeStyles,
  Slide
} from "@material-ui/core";
import clsx from "clsx";
import red from "@material-ui/core/colors/red";

const useStyles = makeStyles(() => ({
    dialog: {
      borderRadius: 0
    },
    button: {
      borderRadius: 0,
      textTransform: "none",
      padding: 5
    },
    logout: {
      color: "#fff",
      backgroundColor: red[500],
      "&amp;:hover": {
        backgroundColor: red[700]
      }
    },
    countdown: {
      color: red[700]
    }
}));

const Transition = React.forwardRef(function Transition(props,ref) {
    return <Slide direction="up" ref={ref} {...props} />;
});

export default function SessionTimeoutDialog({
    open,
    countdown,
    onLogout,
    onContinue
}) {
    const classes = useStyles();
    return (
        <Dialog
            open={open}
            aria-labelledby="session-timeout-dialog"
            aria-describedby="session-timeout-dialog"
            classes={{ paper: classes.dialog }}
            TransitionComponent={Transition}
        >
            <DialogTitle id="session-timeout-dialog-title">
                Session Timeout
            </DialogTitle>
            <DialogContent>
                <Typography variant="body2">
                    The current session is about to expire in{" "}
                    <span className={classes.countdown}>{countdown}</span> seconds.
                </Typography>
                <Typography variant="body2">{`Would you like to continue the session?`}</Typography>
            </DialogContent>
            <DialogActions>
                <Button
                    onClick={onLogout}
                    variant="contained"
                    className={clsx(classes.logout, classes.button)}
                >
                Logout
                </Button>
                <Button
                    onClick={onContinue}
                    color="primary"
                    variant="contained"
                    className={classes.button}
                >
                    Continue Session
                </Button>
            </DialogActions>
        </Dialog>
    );
}

SessionTimeoutDialog.propTypes = {
    /**
     * indicator whether the dialog is open/close
     */
    open: PropTypes.bool.isRequired,
    /**
     * the countdown timer.
     */
    countdown: PropTypes.number.isRequired,
    /**
     * callback function to handle closing action
     */
    onLogout: PropTypes.func.isRequired,
    /**
     * callback function to handle confirm action.
     */
    onContinue: PropTypes.func.isRequired
};

这是一个沙盒示例:https ://codesandbox.io/s/festive-dust-dzt1t

单击继续会话后,如何将超时设置回默认的 30 秒或任何我想要的?

谢谢

标签: reactjssession

解决方案


推荐阅读