Clue Mediator

Implement idle timeout popup in React

📅May 9, 2021

Today we will show you how to implement idle timeout popup in React application.

You may need to develop/integrate the functionality to detect inactive users to auto logout in React. So in this article, we will look the small React Example">React Example to handle the auto logout. In other words, we can say session-based timeout example in react.js.

Checkout more articles on ReactJS

Demo Application

Output - Implement idle timeout popup in React - Clue Mediator

Output - Implement idle timeout popup in React - Clue Mediator

Steps to implement idle timeout popup in React

  1. Create a react app and install npm dependencies
  2. Prepare components for demo
  3. Write a logic to set idle timeout popup
  4. Output

1. Create a react app and install npm dependencies

Let’s create a react app using the `create-react-app` npm package. Run the following command to create a react app.

npx create-react-app idle-timeout-popup-react

For the demo, we will create components (Login & Dashboard) and handle the redirection using routing.

The complete guide of Routing in React.

Here, we will use the following two libraries for this project.

  • bootstrap-modal-popup-using-reactstrap" title="reactstrap">reactstrap for the modal popup and UI.
  • react-idle-timer for the idle timeout.

Run the following command to install the above two libraries.

npm i reactstrap bootstrap react-idle-timer

2. Prepare components for demo

Now, we will simply create two different components such as `Dashboard` & `Login`. By clicking on the `Login` button, we will redirect to the `Dashboard` page and use the `Logout` button to return to the `Login` page.

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

import 'bootstrap/dist/css/bootstrap.css';
import './index.css';

ReactDOM.render(
  <react class="strictmode">
    <app>
  </app></react>,
  document.getElementById('root')
);

App.js

import React from 'react';
import { BrowserRouter, Switch, Route } from 'react-router-dom';

import Login from './Login';
import Dashboard from './Dashboard';

function App() {
  return (
    <browserrouter>
      <div>
        <h5 class="mb-3 d-block">Implement idle timeout popup in React - <a href="https://www.cluemediator.com" target="_blank" rel="noopener">Clue Mediator</a></h5>
        <switch>
          <route exact="" path="/" component={Login}>
          <route path="/dashboard" component={Dashboard}>
        </route></route></switch>
      </div>
    </browserrouter>
  );
}

export default App;

Login.js

import React, { Component } from 'react';

class Login extends Component {

  handleLogin = () => {
    this.props.history.push('/dashboard');
  }

  render() {
    return <div class="w-25">
      <b class="mb-2 d-block">Login</b>
      <input class="d-block mb-2 form-control" type="text" placeholder="Email">
      <input class="d-block mb-2 form-control" type="password" placeholder="Password">
      <button class="btn btn-success" onclick={this.handleLogin}>Login</button>
    </div>
  }
}

export default Login;

Dashboard.js

import React, { Component } from 'react';
import { Table } from 'reactstrap';

class Dashboard extends Component {

  handleLogout = () => {
    this.props.history.push('/');
  }

  render() {
    return <div class="w-25">
      <b class="mb-2 d-block">Dashboard</b>

      <table class="table-bordered">
        <thead>
          <tr>
            <th>#</th>
            <th>First Name</th>
            <th>Last Name</th>
            <th>Username</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <th scope="row">1</th>
            <td>Mark</td>
            <td>Otto</td>
            <td>@mdo</td>
          </tr>
          <tr>
            <th scope="row">2</th>
            <td>Jacob</td>
            <td>Thornton</td>
            <td>@fat</td>
          </tr>
          <tr>
            <th scope="row">3</th>
            <td>Larry</td>
            <td>the Bird</td>
            <td>@twitter</td>
          </tr>
        </tbody>
      </table>

      <button class="btn btn-danger" onclick={this.handleLogout}>Logout</button>
    </div>
  }
}

export default Dashboard;

3. Write a logic to set idle timeout popup

Let’s write a logic to implement idle timeout functionality using `react-idle-timer` and show the modal popup when the user goes idle.

In this example, we will display a popup after 10 seconds of idle time. After displaying the popup, you will be redirected to the login page in 5 seconds. By clicking on the `Stay Logged In` button, we will restart the idle timer and stay on the same page.

Without wasting time, let’s create a modal popup component called `TimeoutModal`.

TimeoutModal.js

import React from 'react';
import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';

const TimeoutModal = ({ showModal, togglePopup, handleStayLoggedIn }) => {
  return <modal isopen={showModal} toggle={togglePopup} keyboard={false} backdrop="static">
    <modalheader>Session Timeout!</modalheader>
    <modalbody>
      Your session is about to expire in 5 seconds due to inactivity. You will be redirected to the login page.
    </modalbody>
    <modalfooter>
      <button color="primary" onclick={handleStayLoggedIn}>Stay Logged In</button>
    </modalfooter>
  </modal>
}

export default TimeoutModal;

In the above component, we are passing the following three attributes.

  • showModal - Flag to show/hide the modal popup.
  • togglePopup - Method to manage the visibility of the modal popup.
  • handleStayLoggedIn - Stay logged in and reset the idle timer.

Let’s import the `react-idle-timer` & `TimeoutModal` in the `Dashboard` to handle the idle timeout popup.

Dashboard.js

...
...

import IdleTimer from 'react-idle-timer';
import TimeoutModal from './TimeoutModal';

class Dashboard extends Component {
  constructor(props) {
    super(props);
    this.state = {
      showModal: false
    }

    this.idleTimer = null;
    this.logoutTimer = null;
  }

  onIdle = () => {
    this.togglePopup();
    this.logoutTimer = setTimeout(() => {
      this.handleLogout();
    }, 1000 * 5 * 1); // 5 seconds
  }

  togglePopup = () => {
    this.setState(prevState => ({ showModal: !prevState.showModal }));
  }

  handleStayLoggedIn = () => {
    if (this.logoutTimer) {
      clearTimeout(this.logoutTimer);
      this.logoutTimer = null;
    }
    this.idleTimer.reset();
    this.togglePopup();
  }

  ...
  ...

  render() {
    const { showModal } = this.state;

    return <div class="w-25">
      <b class="mb-2 d-block">Dashboard</b>

      ...
      ...

      <idletimer ref="{ref" ==""> { this.idleTimer = ref }}
        element={document}
        stopOnIdle={true}
        onIdle={this.onIdle}
        timeout={1000 * 10 * 1} // 10 seconds
      />

      <timeoutmodal showmodal={showModal} togglepopup={this.togglePopup} handlestayloggedin={this.handleStayLoggedIn}>

    </timeoutmodal></idletimer></div>
  }
}

export default Dashboard;

Let’s configure the following properties for the `IdleTimer`.

  • stopOnIdle - Set to `true`, so we can stop the timer when the user goes idle.
  • onIdle - Method to capture an event when the user is idle.
  • timeout - Idle timeout in milliseconds.

4. Output

Run the application and check the output in the browser.

I hope you find this article helpful.
Thank you for reading. Happy Coding..!! 🙂

Demo & Source Code

GitHub Repository StackBlitz Project