I'm struggling with creating a logout feature when users don't make any click event for 30 seconds on the page in React

490 Views Asked by At

I'm struggling with creating a logout feature when users don't make any click event for 30 seconds on the page.

But when the users click anything on the page, the remaining time will be reset to 30 seconds again( or as an other option, clearTimeOut and setTimeOut will be used.) Meanwhile when the users don't click anything on the page, they are gonna be logged out automatically after 30seconds by removing the accessToken.

So to resolve the problem, my approach is like this:

  1. setTimeout() will be begun when the users come over to this page.

  2. when the users click something on the page, clearTimeOut will be active and setTimeOut will be active again too

  3. when the users don't click anything on the page for 30 seconds, they are gonna be logged out automatically by removing the accessToken in the local storage

Currently

  • Make the users logged out by removing the accessToken works!
  • setTimeOut in UseEffect works...

The only matters is

I have no idea how to make clearTimeOut() and setTimeOut work when the users make click event on the page..

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;
3

There are 3 best solutions below

0
Jay On

you can add EventListener for click in useEffect

that will run your function and reset time out

 useEffect(() => {
      document.addEventListener("click", clickDisplay);
      return () => {}
 }, [])
0
Madhan S On
  • Method 1

You can use event listeners in window


    const initIdleCheck = function (callback, timeLimit) {
      let time;
      window.onload = resetTimer;
      document.onload = resetTimer;
      document.onmousemove = resetTimer;
      document.onmousedown = resetTimer;
      document.ontouchstart = resetTimer;
      document.onclick = resetTimer;
      document.onkeypress = resetTimer;
      document.addEventListener('scroll', resetTimer, true);
      
      function resetTimer() {
        clearTimeout(time);
        time = setTimeout(callback, timeLimit)
      }
    };

    initIdleCheck(<IDLE_ACTION_FUNCTION>, <IDLE_TIME>);
    // IDLE_ACTION_FUNCTION - logout in your case

  • Method 2

Use library like idle-js. It provides the same features with customizations.

2
zain ul din On

There are many approaches you can use. let's have a look at one of them

    const [ isClicked , setIsClicked ] = useState(false)

    useEffect ( ()=> {
         const timer = setTimeOut( () => {
            if(isClicked) return;
            // do some thing
            window.history.back()
            // window.close()
         } , yourTime)
         
         return () => { clearTimeout(timer) }

    } , [])

   function onBtnClick () {
      setIsClicked(true)
   }