How to make an idle timer for your React app
Tags: react, webdev
Published: 2023-03-09 14:26:34

**Written by [Ivy Walobwa](https://blog.logrocket.com/author/ivywalobwa/)✏️**


An idle timer is one way to add an additional layer of security to your web application. An idle timer is used to sign out a user after checking whether they’ve been inactive for a specified duration. 

When building websites that contain highly confidential user information, the platform’s security is a major concern. As a developer, you need to guard the end user against intruders. Implementing an idle session timeout to sign a user out of their current session is one way to enhance the platform’s security. 

For example, with applications that make API calls every 30 seconds, it is necessary to implement an idle timeout to improve the app's performance. This logs the user out when idle and prevents unnecessary backend requests. 

In this article, we’ll learn how to implement an idle timeout in your React application. We’ll use the `react-idle-timer` package to detect and respond to the user’s idleness. 

_Jump ahead:_

*   [Events for idle detection in `react-idle-timer`](#events-idle-detection-react-idle-timer)
*   [Getting started](#getting-started)
*   [Creating a custom idle detection Hook](#creating-custom-idle-detection-hook)
*   [Using the idle detection custom Hook](#using-idle-detection-custom-hook)

## Events for idle detection in `react-idle-timer` <a name="events-idle-detection-react-idle-timer">

The DOM API provides mouse and keyboard events that can be used for idle detection. The [`react-idle-timer` package](https://www.npmjs.com/package/react-idle-timer) makes use of the following events to detect user activity:

*   `mousemove` – Fires when a pointing device is moved
*   `keydown` – Fires when a key is pressed
*   `wheel` – Fires when the wheel of a pointing device is rotated
*   `mousedown` – Fires at an element when a button on a pointing device is pressed
*   `touchstart` – Fires when one or more touch points are placed on the touch surface
*   `touchmove` – Fires when one or more touch points are moved along the touch surface
*   `visibilitychange` – Fires at the document when the contents of its tab have become visible or have been hidden
*   `MSPointerDown` – Fires when a pointer becomes active
*   `MSPointerMove` – Fires when a pointer changes coordinates

There are also two deprecated events, `DOMMouseScroll` and `mousewheel`, which we won‘t focus on in this post. 

The `react-idle-timer` package binds all of these events to a DOM element by adding an event listener for each. User idleness is then toggled based on the last time the bound events were triggered.

## Getting started <a name="getting-started">

In your terminal, create a new React application and start the development server using the commands below:

```bash
npx create-react-app idle-timer-react
cd idle-timer-react
yarn start
```

Then, open the React application in your favorite code editor. You will create a simple web application with a `HomePage` and a `Login` page, as shown below. ![Our login page](https://blog.logrocket.com/wp-content/uploads/2023/02/login-page.png) ![Our homepage when we're logged in](https://blog.logrocket.com/wp-content/uploads/2023/02/homepage-logged-in.png) The `App.js` file displays the homepage and login page based on the authentication status.

```javascript
import Login from "./components/Login";
import 'bootstrap/dist/css/bootstrap.min.css';
import { useState } from "react"
import AuthContext from "./context/AuthContext"
import NavigationBar from './components/NavigationBar'
import HomePage from './components/Homepage'

const App = () => {
  const [authstatus, setauthstatus] = useState(false);
  const login = () => {
    setauthstatus(true);
  };
  const logout = () => {
    setauthstatus(false);
  };
  return (
    <AuthContext.Provider value={{ status: authstatus, login: login, logout: logout }}>
      {authstatus ? <>
        <NavigationBar />
        <HomePage />
      </> : <Login />}
    </AuthContext.Provider>
  )
}
export default App;
```

The `HomePage` will contain a displayed text and a modal that will only display when the user is idle.

```javascript
const HomePage = () => {
    const [openModal, setOpenModal] = useState(false)
    const { logout } = useContext(AuthContext);
    const handleIdle = () => {
        setOpenModal(true);
    }
    const stay = () => {
        setOpenModal(false)
    }
    const handleLogout = () => {
        logout()
        setOpenModal(false)
    }
    return <Container className="mt-4">
        <Row>
            <Col></Col>
            <Col>You are now logged in </Col>
            <Col></Col>
        </Row>
        <Modal show={openModal} onHide={stay}>
            <Modal.Header closeButton>
                <Modal.Title>Your session is about to expire</Modal.Title>
            </Modal.Header>
            <Modal.Body>
                <p>
                    Your session is about to expire. You'll be automatically signed out.
                </p>
                <p>
                    Do you want to stay signed in?
                </p>
            </Modal.Body>
            <Modal.Footer>
                <Button variant="secondary" onClick={handleLogout}>
                    Sign out now
                </Button>
                <Button variant="primary" onClick={stay}>
                    Stay signed in
                </Button>
            </Modal.Footer>
        </Modal>
    </Container>
}
export default HomePage;
```

The `Login` signs the user into the application when the login form is submitted.

```javascript
const Login = () => {
    const { login } = useContext(AuthContext);
    const handleLogin = async e => {
        e.preventDefault()
        login();
    };
    return <Container className="mt-5">
        <h1> Please Login</h1>
        <form onSubmit={handleLogin}>
            <p>Password</p>
            <input type="password" />
            <div>
                <button type="submit">
                    Login
                </button>
            </div>
        </form>
    </Container>
}
```

## Creating a custom idle detection Hook <a name="creating-custom-idle-detection-hook">

We can create a custom Hook in our application to implement the `react-idle-timer` package to detect user inactivity. First, install the package using the following command:

```javascript
yarn add react-idle-timer
```

Then, create a `useIdleTimeout.js` file, which we’ll use to contain the custom Hook for idle detection. You can learn more about [creating custom Hooks in this article](https://blog.logrocket.com/create-your-own-custom-react-hooks/). 

Add the code snippet below to the new file:

```javascript
import { useContext, useState } from "react"
import { useIdleTimer } from "react-idle-timer"
import AuthContext from "../context/AuthContext";
/**
 * @param onIdle - function to notify user when idle timeout is close
 * @param idleTime - number of seconds to wait before user is logged out
 */
const useIdleTimeout = ({ onIdle, idleTime = 1 }) => {
    const idleTimeout = 1000 * idleTime;
    const [isIdle, setIdle] = useState(false)
    const { logout } = useContext(AuthContext);
    const handleIdle = () => {
        setIdle(true)
        logout()
    }
    const idleTimer = useIdleTimer({
        timeout: idleTimeout,
        promptTimeout: idleTimeout / 2,
        onPrompt: onIdle,
        onIdle: handleIdle,
        debounce: 500
    })
    return {
        isIdle,
        setIdle,
        idleTimer
    }
}
export default useIdleTimeout;
```

This code contains an implementation of the `useIdleTimer` function from the `react-idle-timer` package. The `useIdleTimeout` Hook expects to call an `onIdle` function when a user is idle, and `idleTime`, which indicates the number of seconds to wait before a user is marked as idle. 

We store the idle state of a user in the `isIdle` state variable. The `useIdleTimer` Hook from the package is called with the following properties:

*   `timeout` – Set the activity timeout, in milliseconds
*   `promptTimeout` – Set the timeout for `onPrompt` to be called
*   `onPrompt` – Displays a confirmation prompt before calling `onIdle`
*   `onIdle` – Called when user is idle
*   [`debounce`](https://blog.logrocket.com/how-and-when-to-debounce-or-throttle-in-react/)

Then we export the `isIdle` state variable, the `setIdle` state action, and the `idleTimer` object.

## Using the idle detection custom Hook <a name="using-idle-detection-custom-hook">

We can now use the custom idle timer Hook in our application. Update the `HomePage` file as shown:

```javascript
const HomePage = () => {
    const [openModal, setOpenModal] = useState(false)
    const { logout } = useContext(AuthContext);
    const handleIdle = () => {
        setOpenModal(true);
    }
    const {idleTimer} = useIdle({ onIdle: handleIdle, idleTime: 5 })
    const stay = () => {
        setOpenModal(false)
        idleTimer.reset()
    }
    const handleLogout = () => {
        logout()
        setOpenModal(false)
    }
    return ...
}
```

In this code, we create an instance of the `useIdle` Hook, which in turn automatically starts the idle timer for us. The idle timer resets when the **Stay signed in** button is clicked. 

When a user stays idle for half of the specified time, we’ll display a prompt. If the user does not interact with the prompt, then they’ll be logged out automatically. However, when they interact with the modal, their interactions produce the following results:

*   When the user clicks the **Close** button, the idle timer is reset and the user stays logged in
*   When the user clicks **Stay signed in**, the idle timer is reset and the user stays logged in
*   When the user clicks **Sign out now**, the user is logged out and the idle timer is destroyed

The video below demonstrates app behavior with an idle timer implemented.<iframe title="YouTube video player" src="https://www.youtube.com/embed/_CB4nrXcuJY" width="560" height="315" frameborder="0" allowfullscreen="allowfullscreen"></iframe>

## Conclusion

Implementing an idle timer can improve the security of your web application. When adding an idle timer, it is important to carefully consider the duration of the timeout based on the user information’s level of risk. It is equally important to provide appropriate timeout notifications to the user to avoid disrupting their workflow. 

In this tutorial, we implemented an idle timer using the [`react-idle-timer` package](https://www.npmjs.com/package/react-idle-timer), which handles the binding and unbinding of keyboard and mouse events for us. We made use of the exposed properties and methods to add an idle timer to our React application. 

All of the code in this article is available on [GitHub](https://github.com/Ivy-Walobwa/react-idle-timer). I hope you enjoyed this tutorial!

---
## Cut through the noise of traditional React error reporting with LogRocket

[LogRocket](https://lp.logrocket.com/blg/react-signup-issue-free) is a React analytics solution that shields you from the hundreds of false-positive errors alerts to just a few truly important items. LogRocket tells you the most impactful bugs and UX issues actually impacting users in your React applications.

[![LogRocket signup](https://blog.logrocket.com/wp-content/uploads/2017/03/1d0cd-1s_rmyo6nbrasp-xtvbaxfg.png)](https://lp.logrocket.com/blg/react-signup-general)

[LogRocket](https://lp.logrocket.com/blg/react-signup-issue-free) automatically aggregates client side errors, React error boundaries, Redux state, slow component load times, JS exceptions, frontend performance metrics, and user interactions. Then LogRocket uses machine learning to notify you of the most impactful problems affecting the most users and provides the context you need to fix it.

Focus on the React bugs that matter — [try LogRocket today](https://lp.logrocket.com/blg/react-signup-issue-free).