An idle timeout is a feature implemented in most web applications for user activity detection.
In simple terms, it is used to check whether a user has been inactive(away from the app or computer) for a specified amount of time.
Often, an action gets executed after the time of inactivity set is exceeded.
Why we need an idle Timeout.
An idle timout can be used for various purposes like logging a user out of the site if the user is inactive, this is crucial for high risk web apps to enhance security of the application. Logging out a user is also important to improve perfomance of the application by avoiding unnecesarry API calls on the site since the user is inactive. Setting an idle timeout is also a great user experience practice because many at times a user might forget the reason for accessing the site, logging the user out can help in refreshing the user's memory. Many times instead of directly logging a user out of your application you may want to prompt the user on the next action to be taken, whether to log out or continue using the site.
An example use case is when you're watching a long series on Netflix, Netflix might ask you if you are still there and you are given an option of cancelling or continuing the series. In this article we're going to learn how to implement an idle timeout in your React applications by checking if the user is idle or not and asking them whether they want to stay logged in or logout of the site.
How to detect if a user is idle in your application
We first need to detect whether a user is active or not. You can easily have activity detection in your application by installing the react-idle-timer package, but it is important to know some of the functionality the package uses under the hood to make it happen. We will first write the functionality using state that detects the user's active state using some DOM events.
Using React's useState and useEffect hooks
Assuming you have already initialized a react app using create-react-app. You should have a folder structure similar to this.
Inside the App.js file, we can write a script that console logs "The user is inactive" if a user does not perform any of the eventListeners on the application's window and display's a simple text on the UI that check's the state of active whether true or false
//App.js//import the required useEffect and useState from ReactimportReact,{useEffect,useState}from"react"//Our App component which will be exported as default to our index.js file for rendering.constApp=()=>{//creating a variable (active) to store our boolean and a function (setActivity) to change our variable's value to either true or false const[active,setActivity]=useState(true)constcheckForInactivity=()=>{//Grabs the expired time from the local storage in our browser, store it in a variable called expireTimeconstexpireTime=localStorage.getItem("expireTime")//sets the activity state to false if the expireTime is earlier than the current timeif(expireTime<Date.now()){console.log("The user is inactive")setActivity(false)}}constupdateExpireTime=()=>{//sets the expire timer to 5 seconds after the current date(time to wait to log out the user after detecting inactiviy), you can modify the valuesconstexpireTime=Date.now()+5000//sets the value of the localStorage's expire timelocalStorage.setItem("expireTime",expireTime)}//runs only once when the component is mountuseEffect(()=>{//checks the expire time after every 2 seconds(you can modify the values)constinterval=setInterval(()=>{checkForInactivity()},1000)//clears the interval setreturn()=>{clearInterval(interval)}},[])//runs only once when the component is mountuseEffect(()=>{//updates the expire timeupdateExpireTime()//event listensers to detect user activity, click, keypress, scroll, mousemovewindow.addEventListener("click",updateExpireTime)window.addEventListener("keypress",updateExpireTime)window.addEventListener("scroll",updateExpireTime)window.addEventListener("mousemove",updateExpireTime)//cleansup the event listenersreturn()=>{window.removeEventListener("click",updateExpireTime)window.removeEventListener("keypress",updateExpireTime)window.removeEventListener("scroll",updateExpireTime)window.removeEventListener("mousemove",updateExpireTime)}},[])return(//stringifies the value of the active variable to display on the browser<div>Active : {active.toString()}</div>)}
Code explanation
The useState() hook creates a variable called active with an initial value of true and a function called setActive which will toggle the active variable to false when the user does not perform any of the eventListeners created after 5 seconds.
The checkForInactivity() function gets a key called expireTime from the localStorage of our browser which we will create in our updateExpireTime() function, the local storage stores data with no expiration date, you can read more about local storage. After getting the data, it compares the expireTime with your current time of which if the expireTime was earlier than the date it console logs "The user is inactive"
The updateExpireTime() function creates a new Item called expireTime inside our local storage which is set to your current time added to 5 seconds (you can adjust the time to your desired time), the expireTime is what the script uses to determine the time taken to logout the user if idle.
The first useEffect() has variable called interval which sets the interval of checking the expired time after every 1 seconds using the setInterval() method. The setInterval takes in checkForInactivity() as it's first argument and the desired time as the second argument(checks after every 1 seconds). It returns a function that clears the interval from the window and stops the interval.
The second useEffect() hook is where we have the desired eventListeners and takes updateExpireTime() as the function which simply updates the expireTime to refresh if the user is active. It runs only once when the component mounts because we declared an empty dependancy array as it's seconf argument. Some of the events used are click, scroll, mousemove, keypress, you may add your desired events to detect user inactivity. It alse cleans up the window by returning a function that removes the eventListeners from the window.