繁体   English   中英

在会话结束前提示用户

[英]Prompt user before the session ends

我需要显示一个对话框,其中显示当前会话到期的剩余时间。 我已经实现了它,不幸的是,计时器正在滴答多次。这是我的代码。

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将显示在对话框中。

我在代码中做了一些更改。

  1. 我正在使用useRef来保存组件的状态。 因此,在useEffect我正在检查组件是否已安装,然后从localStorageprops值设置计时器值,并且在后续更新中useEffect将不会执行if (init.current)块内的代码。

useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传递的参数 (initialValue)。 返回的对象将在组件的整个生命周期内持续存在

注意 useRef 不会在其内容更改时通知您。 改变 .current 属性不会导致重新渲染。

  1. 我使用setTimeout在每 1 秒后更新sessionTimeout状态以更新计时器,因此状态更新将在每次更新后执行useEffect挂钩,因为sessionTimeout包含在useEffect依赖项中。

尝试这个。

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>
  );
}


现场示例

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

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