简体   繁体   English

在会话结束前提示用户

[英]Prompt user before the session ends

I need to display a dialog box where it shows the remaining time for the current session to expire.我需要显示一个对话框,其中显示当前会话到期的剩余时间。 I have implemented it, unfortunately,the timer is ticking multiple times.Here is my code.我已经实现了它,不幸的是,计时器正在滴答多次。这是我的代码。

warningTime and timeout value is fetched from the api which is in parent component. warningTime timeouttimeout值是从父组件中的 api 获取的。

const [ remainingTime, setRemainingTime ] = useState(warningTime);

    useEffect(() => {
        let interval = null;
        if (timeout > 0) {
        let sessionTimeoutInterval = setInterval(() => {
            let runTime = localStorage.getItem("timeout");
            if (parseInt(runTime) === warningTime) {
                openDialog();
                if(remainingTime===warningTime) {
                    interval = setInterval(() => {
                        if (remainingTime > 0) {
                            setRemainingTime(remainingTime => remainingTime - 1);
                        }
                    }, 1000);
                }
                if(remainingTime === 0) {
                    handleDialogClose();
                    clearInterval(interval);
                }
            } else{
                localStorage.setItem("timeout", --runTime); 
            }
        }, 1000);
        if (remainingTime === 0) {
            handleDialogClose();
            handleLogout();
        }
        return () => {
            clearInterval(sessionTimeoutInterval);
        };
        }
    }, [timeout, remainingTime, warningTime ]);

remainingTime will be displayed in dialog. remainingTime将显示在对话框中。

I have made couple of change in the code.我在代码中做了一些更改。

  1. I am using useRef to hold the status of the component.我正在使用useRef来保存组件的状态。 So in useEffect i am checking if the component is mounted and then setting the timer value from the localStorage or from the props value and on subsequent updates useEffect will not execute the code inside if (init.current) block.因此,在useEffect我正在检查组件是否已安装,然后从localStorageprops值设置计时器值,并且在后续更新中useEffect将不会执行if (init.current)块内的代码。

useRef returns a mutable ref object whose .current property is initialized to the passed argument (initialValue). useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传递的参数 (initialValue)。 The returned object will persist for the full lifetime of the component返回的对象将在组件的整个生命周期内持续存在

Note useRef doesn't notify you when its content changes.注意 useRef 不会在其内容更改时通知您。 Mutating the .current property doesn't cause a re-render.改变 .current 属性不会导致重新渲染。

  1. I am using setTimeout to update the sessionTimeout state after every 1 second to update the timer, so the state update will execute the useEffect hook after each update as the sessionTimeout in included in the useEffect dependency.我使用setTimeout在每 1 秒后更新sessionTimeout状态以更新计时器,因此状态更新将在每次更新后执行useEffect挂钩,因为sessionTimeout包含在useEffect依赖项中。

Try this.尝试这个。

import React, { useEffect, useState, useRef } from "react";
import DialogBox from "./DialogBox";
import Logout from "./Logout";

export default function Child({ warningTime, timeout }) {
  const [showDialog, setShowDialog] = useState(false);
  const [showLogout, setShowLogout] = useState(false);
  const [sessionTimeout, setSessionTimeout] = useState(timeout);
  const init = useRef(true);
  const progressbar = useRef(warningTime);

  useEffect(() => {
    if (init.current) {
      init.current = false;
      let sessionTime = localStorage.getItem("timeout");

      if (sessionTime && sessionTime < warningTime) {
        progressbar.current = sessionTime;
      } else {
        progressbar.current = warningTime;
      }

      if (sessionTime) {
        setSessionTimeout(prevState => sessionTime);
      } else {
        localStorage.setItem("timeout", sessionTimeout);
      }
    }

    let sessionTimeoutInterval = null;
    if (sessionTimeout > 0) {
      sessionTimeoutInterval = setTimeout(() => {
        if (sessionTimeout <= warningTime) {
          openDialog();
        }
        setSessionTimeout(sessionTimeout => {
          let updatedtime = sessionTimeout - 1;
          localStorage.setItem("timeout", updatedtime);
          return updatedtime;
        });
      }, 1000);
    } else {
      localStorage.removeItem("timeout");
      handleDialogClose();
      handleLogout();
      clearTimeout(sessionTimeoutInterval);
    }
    return () => {
      if (sessionTimeoutInterval) clearTimeout(sessionTimeoutInterval);
    };
  }, [sessionTimeout]);

  function openDialog() {
    setShowDialog(true);
  }

  function handleDialogClose() {
    setShowDialog(false);
  }

  function handleLogout() {
    setShowLogout(true);
  }

  function addMoreTimeHandler() {
    handleDialogClose();
    setSessionTimeout(sessionTimeout => {
      localStorage.setItem("timeout", timeout);
      return timeout;
    });
  }

  return (
    <div>
      {showLogout ? <Logout /> : "Time remaning: " + sessionTimeout}
      {showDialog ? (
        <DialogBox
          progressBar={progressbar.current - 1}
          sessionTimeout={sessionTimeout}
          addMoreTime={addMoreTimeHandler}
        />
      ) : null}
    </div>
  );
}


Live Example现场示例

在会话结束前编辑提示用户

I tried to simulate your code with dummy data and it worked.

let [ remainingTime, setRemainingTime, sessionTimeout, warningTime] = [1000, 5000, 10000, 1000];
let runTime = 3000;

   function abc() {
        let interval = null;
        if (sessionTimeout > 0) {
        let sessionTimeoutInterval = setInterval(() => {
            if (parseInt(runTime) === warningTime) {
                // openDialog();
console.log("open dialog");
                if(remainingTime===warningTime) {
                    interval = setInterval(() => {
                        if (remainingTime > 0) {
                            remainingTime -= 1000;
                        }
                    }, 1000);
                }
                if(remainingTime === 0) {
                    // handleDialogClose();
console.log("close dialog");
                    clearInterval(interval);
clearInterval(sessionTimeoutInterval);
                } 
            } else {
if(runTime > 0){ // this condition is newly added
                runTime-=1000; }
            }
        }, 1000);
        }
    }
abc();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM