我有一个需要空闲超时的应用程序,它首先警告用户他们将在一分钟内注销,然后在一分钟到期后将用户注销。
我已经成功地使用了一个类组件,如下面的帖子所示:
使用反应的会话超时警告模式
我正在将我的应用程序的代码移动到 React Hooks,但我很难移动这段代码。我尝试了以下方法:
const [signoutTime, setSignoutTime] = useState(0);
let warnTimeout;
let logoutTimeout;
const setTimeout = () => {
warnTimeout = setTimeout(warn, warningTime);
logoutTimeout = setTimeout(logout, signoutTime);
};
const clearTimeout = () => {
if (warnTimeout) clearTimeout(warnTimeout);
if (logoutTimeout) clearTimeout(logoutTimeout);
};
useEffect(() => {
setWarningTime(10000);
setSignoutTime(15000);
const events = [
'load',
'mousemove',
'mousedown',
'click',
'scroll',
'keypress'
];
const resetTimeout = () => {
clearTimeout();
setTimeout();
};
for (var i in events) {
window.addEventListener(events[i], resetTimeout);
}
setTimeout();
});
const warn = () => {
console.log('Warning');
};
const destroy = () => {
console.log('Session destroyed');
};
最后,我希望出现一种模式来警告用户即将注销。如果用户移动鼠标、单击等(请参阅事件(,则计时器将重置。如果用户单击模式中的按钮,计时器将重置。
非常感谢您的帮助!
试试这个
mport React, { useEffect, useState } from 'react';
const LogoutPopup = () => {
const [signoutTime, setSignoutTime] = useState(10000);
const [warningTime, setWarningTime] = useState(15000);
let warnTimeout;
let logoutTimeout;
const warn = () => {
console.log('Warning');
};
const logout = () => {
console.log('You have been loged out');
}
const destroy = () => {
console.log('Session destroyed');
}
const setTimeouts = () => {
warnTimeout = setTimeout(warn, warningTime);
logoutTimeout = setTimeout(logout, signoutTime);
};
const clearTimeouts = () => {
if (warnTimeout) clearTimeout(warnTimeout);
if (logoutTimeout) clearTimeout(logoutTimeout);
};
useEffect(() => {
const events = [
'load',
'mousemove',
'mousedown',
'click',
'scroll',
'keypress'
];
const resetTimeout = () => {
clearTimeouts();
setTimeouts();
};
for (let i in events) {
window.addEventListener(events[i], resetTimeout);
}
setTimeouts();
return () => {
for(let i in events){
window.removeEventListener(events[i], resetTimeout);
clearTimeouts();
}
}
},[]);
return <div></div>
}
export default LogoutPopup;
基于第一个答案,当您还需要用户注销之前的时间时,我有另一个钩子解决方案。
代码沙盒演示
使用自动注销.js
import React, { useEffect, useState } from "react";
const useLogout = (startTime) => {
const [timer, setTimer] = useState(startTime);
useEffect(() => {
const myInterval = setInterval(() => {
if (timer > 0) {
setTimer(timer - 1);
}
}, 1000);
const resetTimeout = () => {
setTimer(startTime);
};
const events = [
"load",
"mousemove",
"mousedown",
"click",
"scroll",
"keypress"
];
for (let i in events) {
window.addEventListener(events[i], resetTimeout);
}
return () => {
clearInterval(myInterval);
for (let i in events) {
window.removeEventListener(events[i], resetTimeout);
}
};
});
return timer;
};
export default useLogout;
应用.js
import useAutoLogout from "./useAutoLogout";
function App() {
const timer = useAutoLogout(10);
if (timer == 0) {
return <div>Logged Out</div>;
}
if (timer < 8) {
return <div>In {timer} seconds you will be automatically logged out</div>;
}
return <div>Signed in</div>;
}
export default App;
我稍微重写了你的答案以摆脱衬里错误,我认为将其提取到钩子中也很方便,这样你只需要传入你想要的参数,这就消除了对计时器状态的需要。
我想useCallback是为了提高效率,以阻止它在每次渲染上自行工作,
我已经在UseEffect中移动了一些其他东西,以摆脱那些linting错误!
import React, { useCallback } from 'react'
function useMonitor({ timeout, warningTimeout, onWarn, onTimeOut }) {
const warn = useCallback(()=> {
onWarn && onWarn()
},[onWarn])
const logout = useCallback(()=> {
onTimeOut && onTimeOut()
},[onTimeOut])
React.useEffect(() => {
let warnTimeout;
let logoutTimeout;
const setTimeouts = () => {
warnTimeout = setTimeout(warn, warningTimeout);
logoutTimeout = setTimeout(logout, timeout);
};
const clearTimeouts = () => {
if (warnTimeout) clearTimeout(warnTimeout);
if (logoutTimeout) clearTimeout(logoutTimeout);
};
const events = [
'load',
'mousemove',
'mousedown',
'click',
'scroll',
'keypress'
];
const resetTimeout = () => {
clearTimeouts();
setTimeouts();
};
for (let i in events) {
window.addEventListener(events[i], resetTimeout);
}
setTimeouts();
return () => {
for (let i in events) {
window.removeEventListener(events[i], resetTimeout);
clearTimeouts();
}
}
}, [logout, timeout, warn, warningTimeout]);
}
export default useMonitor