[英]Prompt user before the session ends
我需要显示一个对话框,其中显示当前会话到期的剩余时间。 我已经实现了它,不幸的是,计时器正在滴答多次。这是我的代码。
warningTime
timeout
和timeout
值是从父组件中的 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
将显示在对话框中。
我在代码中做了一些更改。
useRef
来保存组件的状态。 因此,在useEffect
我正在检查组件是否已安装,然后从localStorage
或props
值设置计时器值,并且在后续更新中useEffect
将不会执行if (init.current)
块内的代码。useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传递的参数 (initialValue)。 返回的对象将在组件的整个生命周期内持续存在
注意 useRef 不会在其内容更改时通知您。 改变 .current 属性不会导致重新渲染。
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.