IMPLEMENTING APP SESSION TIMEOUT IN React.JS
Tags: webdev, react, mern, javascript
Published: 2023-12-31 19:41:25

## Introduction

Let's start by defining what a session timeout is in web applications. A session timeout occurs when inactivity on a webpage is detected after a certain amount of time. If you have not selected to persist, your session will time out, and you will be logged out. I'm sure most of us have experienced something similar to this:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/71ukua7azroe4yzcfh61.png)

## Is a timeout truly necessary?

Most web applications may not require timeout functionality; however, if you are developing a project that handles sensitive user information or a financial application where users perform transactions and leave their money in your care, timeout functionality that monitors user activity and triggers some action when a set time elapses is critical. Some of the benefits are as follows:

**Resource Management** The timeout feature allows you to release and free server resources associated with a user session. This is especially important when resources are limited, and it is crucial to manage and release resources when they are no longer needed.

**Compliance with Security Standards** Many security standards and best practices advocate the use of timeouts to avoid session hijacking and unauthorized access. Adherence to these standards contributes to the security and compliance of the application.

**Security and Privacy Enhancement** Timeouts reduce the risk of unauthorized access to a user's account. An automatic timeout ensures that the session finishes after a certain length of time if the user forgets to log out or leaves the app alone.

**Prevention of Accidental Data Exposure** Timeouts limit the possibility of unintentional data disclosure in cases where users forget to log out by terminating sessions automatically.

Let's go ahead and integrate timeout functionality into an app now that we've demonstrated its importance.

## Timeout implementation in React.


We begin by using **Vite** to bootstrap our React app. Vite is a build tool that improves the development process for modern web applications that use JavaScript frameworks such as **Vue.js** and **React**. It focuses on delivering a quick and efficient development environment by using browsers' native ES Module (ESM) capabilities. To learn more about Vite see here [Vite](https://vitejs.dev/).

We will start by bootstrapping our React app using Vite, to do this we first navigate to a directory where we will create our project.

Let's start by creating a new folder 📂 on the desktop, and give it the name **app**. 

Open Visual Studio Code and drag the app-timeout folder we just created onto it. And after pressing Ctrl + Tab Keys, you can see we're in our app directory.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sq6fj460k38s9djeupfs.PNG)


Let's add the following commands to set up our app.

```
npm create vite@latest
// select Typescript as the preferred language, and
// specify the project name, here it is app-timeout
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xfsad09jxcru1ho57mrg.PNG)
Run the following command to open our project directory:

```
cd app-timeout
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4v373f1fccxt3evv6hvz.PNG)

Run the following command to add the required dependencies:

```
npm install
```

To run our application, add the following command and hit enter:

```
npm run dev
```


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sneb79z8dxc2jsa5wvea.PNG)

Click the **http://localhost:5173/** and see your app in action.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1bkezhb83py9jluji1vk.PNG)

We also need to install **react-router-dom** and **@types/node**, to help with routing and provide the appropriate types we need respectively. Run the code below to do this:

```
npm i react-router-dom 
npm install --save-dev @types/node

```
In the **src** folder, create a new folder named **components**, in there create another folder called providers and in there create a file and name it timeout-provider.tsx. In this file, add the following code:

```

```


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g1k4ipotgxgss6lx9ces.PNG)

```
import { ReactNode, useEffect, useRef } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';

export function TimeoutProvider({ children }: { children: ReactNode }) {
  const navigate = useNavigate();
  const location = useLocation();
  const timeoutRef = useRef<NodeJS.Timeout>();

  useEffect(() => {
    if (exemptedRoutes.includes(location.pathname)) return;
    const handleWindowEvents = () => {
      clearTimeout(timeoutRef.current);

      timeoutRef.current = setTimeout(() => {
        //Perform whatever logic you want in here, clear localStorage and log user out, show a popup modal or just navigate to another page
        navigate('/2024');
      }, 10000);
    };

    // listen for specific window events to ensure user is still active
    window.addEventListener('mousemove', handleWindowEvents);
    window.addEventListener('keydown', handleWindowEvents);
    window.addEventListener('click', handleWindowEvents);
    window.addEventListener('scroll', handleWindowEvents);

    handleWindowEvents();

    //cleanup function
    return () => {
      window.removeEventListener('mousemove', handleWindowEvents);
      window.removeEventListener('keydown', handleWindowEvents);
      window.removeEventListener('click', handleWindowEvents);
      window.removeEventListener('scroll', handleWindowEvents);
    };
  }, [navigate, location.pathname]);

  return children;
}

const exemptedRoutes = ['/404', '/sign-up', '/forgot-password'];

```

Let's get straight to the business and understand what's happening here in this code. 

This code implements a feature for a web application that aids in the management of user activity by automatically redirecting users to a specified page if they have been idle for some time.

This code implements a feature for a web application that aids in the management of user activity by automatically redirecting users to a specified page if they have been idle for a period of time.

Let's break down the code:

**TimeoutProvider:** Think of it as a controller or manager. It watches what you're doing on the website.

**Hooks and References:** These are like tools it uses to understand what's happening. It listens to where you are on the website (location) and how to move you around (navigate).

**Setting a Timer:** The code sets a timer for 10 seconds. If you're not moving the mouse, pressing keys, clicking, or scrolling during this time, it decides you're inactive and triggers an action (like going to a specific page).

**Ignoring Certain Pages:** Some pages don't trigger this timer, like when you're signing up or recovering a forgotten password. It doesn't redirect you from these pages.

Let's update the code in the **main.tsx** file with the code below:

```
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App.tsx';
import './index.css';

import { RouterProvider, createBrowserRouter } from 'react-router-dom';
import { Home } from './pages/Home.tsx';
import { NextYear } from './pages/2024.tsx';

const router = createBrowserRouter([
  {
    path: '/',
    element: <App />,
    children: [
      {
        path: '/',
        element: <Home />,
      },
      {
        path: '/2024',
        element: <NextYear />,
      },
    ],
  },
]);

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <RouterProvider router={router} />
  </React.StrictMode>
);

```
In the code above, we create our router and map each route to its corresponding component.

In the **src** folder, create a new folder called **pages** and in there create two new files called **Home.tsx** and **2024.tsx**

In **Home.tsx** put the following code:

```
export function Home() {
  return (
    <div>
      <p style={{ fontSize: '2rem', fontWeight: 'bold' }}>Goodbye 2023, you were the year that made us laugh, cry, and Google everything!🫡</p>
    </div>
  );
}

```

In **2024.tsx** put the following code:

```
export function NextYear() {
  return (
    <div>
      <p style={{ fontSize: '2rem', fontWeight: 'bold' }}>Welcome to 2024!!!🎉🍾🎊</p>
    </div>
  );
}

```

Finally, update the code in **App.tsx** to the following:

```
import './App.css';
import { Outlet } from 'react-router-dom';
import { TimeoutProvider } from './components/providers/timeout-provider';

function App() {
  return (
    <TimeoutProvider>
      <Outlet />
    </TimeoutProvider>
  );
}

export default App;

```
We've ensured that our **timeout** feature is available to all pages in the React project, save those that are exempted, by wrapping Outlet in the **TimeoutProvider** we developed. As a result, the purpose of adding a timeout for a React application is met.

**See the photo below before the session timeout:**

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jsv0b82b52uvd6rwyn4s.PNG)

**And a photo after the session timeout:**


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ljbo5z7z75yu511vmfx0.PNG)


## Conclusion

As I'm about to wrap up this article, it feels like I've reached a timeout for the year 2023. Just like a session that's naturally timed out, bidding farewell to the quirky bugs, unexpected errors, and delightful surprises of 2023.

Now, as the clock ticks and the page refreshes to 2024, let's gear up for a new session in the software of life! May this new year be as bug-free as a perfectly coded app and filled with updates that bring joy, laughter, and perhaps a few pleasant surprises, just like discovering an Easter egg in the code.

So, here's to embracing the unknowns, debugging life's glitches, and exploring new routes in the journey ahead. Wishing everyone a happy new year—may your sessions never time out, except when it's for a well-deserved break!