React 中的 setTimeout 和 clearTimeout
setTimeout and clearTimeout in React
当用户使用 setTimeout 和 clearTimeout 在页面上 30 秒内未进行任何点击事件时,我正在努力创建注销功能。
但是每次用户点击页面上的任何东西,剩余时间必须重新设置为30秒(或者作为另一个选项,将使用clearTimeOut和setTimeOut。)同时当用户没有点击任何东西时在页面上,他们将在 30 秒后通过删除 accessToken 自动注销。
所以要解决这个问题,我的做法是这样的:
setTimeout() 将在用户访问此页面时开始。
当用户单击页面上的某些内容时,clearTimeOut 将被激活并且 setTimeOut 将再次被激活
当用户在 30 秒内没有点击页面上的任何内容时,他们将通过删除本地存储中的 accessToken 自动注销
目前通过删除 accessToken 使用户在 30 秒后注销有效!
UseEffect 中的 setTimeOut 也有效。
唯一的问题是当用户在页面上点击事件时,我不知道如何使 clearTimeOut() 和 setTimeOut 工作..
import styled from 'styled-components';
import React, {useRef, useEffect, useState} from 'react';
import ScreenContainer from '../../src/component/common/ScreenContainer';
import {useNavigate as useDomNavigate} from 'react-router-dom';
import isNil from 'lodash/isNil';
import userClient from '../../src/client/user/userClient';
const Device = () => {
const domNavigate = useDomNavigate();
const [storeId, setStoreId] = useState(() => JSON.parse(localStorage.getItem('storeId')));
const [currentDeposit, setCurrentDeposit] = useState<number>(0);
const depositBalanceInfo = userClient.getDepositBalanceByStoreId(storeId, isNil(storeId)).data;
const [time, setTime] = useState(1500);
const logout = () => {
localStorage.removeItem('accessToken');
domNavigate(`/home/home`);
};
//////////////////////////
// below is the code that I wrote to make it work..
const myFunc = () => {
// remove accessToken for logout
localStorage.removeItem('accessToken');
// move to home page
domNavigate(`/home/home`);
}
// begin setTimeOut automatically when the users come over to this page from another one.
useEffect(() => {
const timeoutBegins = window.setTimeout(myFunc, 3000);
return () => clearTimeout(timeoutBegins);
}, [])
// when the users click anything on the page, it clears current setTimeOut function and restart the setTimeOut function again.
const clickDisplay = () => {
clearTimeout(timeoutBegins);
timeOutBegins();
}
/////////////////////////////////////////
useEffect(() => {
if (storeId && depositBalanceInfo) {
setCurrentDeposit(depositBalanceInfo?.depositBalance);
}
}, [storeId, depositBalanceInfo?.depositBalance]);
return (
<ScreenContainer>
<Wrapper>
<div>Choose Payment Option</div>
<button onClick={() => window.history.back()}>go back</button>
<div>Your Balance: {currentDeposit.toLocaleString()}dollar</div>
<br />
<button onClick={() => domNavigate(`/charge/step2-select-price/?chargeMethod=card`)}>Credit Card Payment</button>
<br />
<button onClick={() => domNavigate(`/charge/step2-select-price/?chargeMethod=cash`)}>Cash Payment</button>
<br />
<button onClick={() => domNavigate(`/home/checkUserByPin`)}>Reset Password</button>
<br />
<button onClick={logout}>Logout</button>
</Wrapper>
</ScreenContainer>
);
};
const Wrapper = styled.div`
border: 1px solid red;
`;
export default Device;
您的代码段中跳出了几个问题:
timeoutBegins
仅限于您的 useEffect
回调,因此不适用于 clickDisplay
。
clickDisplay
未附加到任何事件侦听器
timeoutBegins
不可调用,是定时器ID
注意:创建一个 minimal reproducable example 是个好主意,因为这将帮助您和审阅者消除问题。
解决方案:
let timerId;
function Device() {
const logOutUser = () => {
// log out code...
};
const startTimer = () => {
if (timerId) clearTimeout(timerId);
timerId = setTimeout(logOutUser, 3000);
}
const stopTimer = () => clearTimeout(timerId);
useEffect(() => {
// start timer when component is mounted
startTimer();
// stop timer when component is unmounted
return stopTimer;
}, []);
return <div onClick={startTimer}></div>;
}
你可以这样做。因此,您 运行 计时器,每次单击文档中的某个位置时,它都会取消当前计时器并 运行 新计时器。因此,仅当用户在 N 秒后未单击该页面时,您的 myFunc
函数才会 运行。
记住,你想在 30 秒内完成,你需要在 setTimeout
中输入 30000
const timerId = useRef(null)
const myFunc = () => {
clearTimeout(timerId.current)
timerId.current = null
console.log('DO SOMETHING')
}
const onDocumentClick = () => {
if (timerId.current) {
clearTimeout(timerId.current)
timerId.current = window.setTimeout(myFunc, 3000)
}
}
useEffect(() => {
timerId.current = window.setTimeout(myFunc, 3000)
document.addEventListener('click', onDocumentClick)
return () => {
clearTimeout(timerId.current)
document.removeEventListener('click', onDocumentClick)
}
}, [])
当用户使用 setTimeout 和 clearTimeout 在页面上 30 秒内未进行任何点击事件时,我正在努力创建注销功能。
但是每次用户点击页面上的任何东西,剩余时间必须重新设置为30秒(或者作为另一个选项,将使用clearTimeOut和setTimeOut。)同时当用户没有点击任何东西时在页面上,他们将在 30 秒后通过删除 accessToken 自动注销。
所以要解决这个问题,我的做法是这样的:
setTimeout() 将在用户访问此页面时开始。
当用户单击页面上的某些内容时,clearTimeOut 将被激活并且 setTimeOut 将再次被激活
当用户在 30 秒内没有点击页面上的任何内容时,他们将通过删除本地存储中的 accessToken 自动注销
目前通过删除 accessToken 使用户在 30 秒后注销有效! UseEffect 中的 setTimeOut 也有效。
唯一的问题是当用户在页面上点击事件时,我不知道如何使 clearTimeOut() 和 setTimeOut 工作..
import styled from 'styled-components';
import React, {useRef, useEffect, useState} from 'react';
import ScreenContainer from '../../src/component/common/ScreenContainer';
import {useNavigate as useDomNavigate} from 'react-router-dom';
import isNil from 'lodash/isNil';
import userClient from '../../src/client/user/userClient';
const Device = () => {
const domNavigate = useDomNavigate();
const [storeId, setStoreId] = useState(() => JSON.parse(localStorage.getItem('storeId')));
const [currentDeposit, setCurrentDeposit] = useState<number>(0);
const depositBalanceInfo = userClient.getDepositBalanceByStoreId(storeId, isNil(storeId)).data;
const [time, setTime] = useState(1500);
const logout = () => {
localStorage.removeItem('accessToken');
domNavigate(`/home/home`);
};
//////////////////////////
// below is the code that I wrote to make it work..
const myFunc = () => {
// remove accessToken for logout
localStorage.removeItem('accessToken');
// move to home page
domNavigate(`/home/home`);
}
// begin setTimeOut automatically when the users come over to this page from another one.
useEffect(() => {
const timeoutBegins = window.setTimeout(myFunc, 3000);
return () => clearTimeout(timeoutBegins);
}, [])
// when the users click anything on the page, it clears current setTimeOut function and restart the setTimeOut function again.
const clickDisplay = () => {
clearTimeout(timeoutBegins);
timeOutBegins();
}
/////////////////////////////////////////
useEffect(() => {
if (storeId && depositBalanceInfo) {
setCurrentDeposit(depositBalanceInfo?.depositBalance);
}
}, [storeId, depositBalanceInfo?.depositBalance]);
return (
<ScreenContainer>
<Wrapper>
<div>Choose Payment Option</div>
<button onClick={() => window.history.back()}>go back</button>
<div>Your Balance: {currentDeposit.toLocaleString()}dollar</div>
<br />
<button onClick={() => domNavigate(`/charge/step2-select-price/?chargeMethod=card`)}>Credit Card Payment</button>
<br />
<button onClick={() => domNavigate(`/charge/step2-select-price/?chargeMethod=cash`)}>Cash Payment</button>
<br />
<button onClick={() => domNavigate(`/home/checkUserByPin`)}>Reset Password</button>
<br />
<button onClick={logout}>Logout</button>
</Wrapper>
</ScreenContainer>
);
};
const Wrapper = styled.div`
border: 1px solid red;
`;
export default Device;
您的代码段中跳出了几个问题:
timeoutBegins
仅限于您的useEffect
回调,因此不适用于clickDisplay
。clickDisplay
未附加到任何事件侦听器timeoutBegins
不可调用,是定时器ID
注意:创建一个 minimal reproducable example 是个好主意,因为这将帮助您和审阅者消除问题。
解决方案:
let timerId;
function Device() {
const logOutUser = () => {
// log out code...
};
const startTimer = () => {
if (timerId) clearTimeout(timerId);
timerId = setTimeout(logOutUser, 3000);
}
const stopTimer = () => clearTimeout(timerId);
useEffect(() => {
// start timer when component is mounted
startTimer();
// stop timer when component is unmounted
return stopTimer;
}, []);
return <div onClick={startTimer}></div>;
}
你可以这样做。因此,您 运行 计时器,每次单击文档中的某个位置时,它都会取消当前计时器并 运行 新计时器。因此,仅当用户在 N 秒后未单击该页面时,您的 myFunc
函数才会 运行。
记住,你想在 30 秒内完成,你需要在 setTimeout
const timerId = useRef(null)
const myFunc = () => {
clearTimeout(timerId.current)
timerId.current = null
console.log('DO SOMETHING')
}
const onDocumentClick = () => {
if (timerId.current) {
clearTimeout(timerId.current)
timerId.current = window.setTimeout(myFunc, 3000)
}
}
useEffect(() => {
timerId.current = window.setTimeout(myFunc, 3000)
document.addEventListener('click', onDocumentClick)
return () => {
clearTimeout(timerId.current)
document.removeEventListener('click', onDocumentClick)
}
}, [])