How to use the new IdleTimer from 'react-idle-timer' in a functional component

5.8k views Asked by At

The IdleTimer was rewritten from scratch in v5, and the usage changed completely. They do have an example of how use it "the old way", but it's written for class based components. I need help translating that to a functional component.

This is their example:

  import { Component } from 'react'
  import { withIdleTimer } from 'react-idle-timer'

  class IdleTimerComponent extends Component {
    render () {
      return this.props.children
    }
  }

  export const IdleTimer = withIdleTimer(IdleTimerComponent)

and then use it like this from the app:

render () {
    return (
      <>
        <IdleTimer
          ref={ref => { this.idleTimer = ref }}
          timeout={1000 * 60 * 15}
          promptTimeout={1000 * 30}
          onPrompt={this.onPrompt}
          onIdle={this.onIdle}
          onAction={this.onAction}
          onActive={this.onActive}
          startManually
        />
        <HomePage />
      </>
    )
  }

How do I do this in a functional component?

3

There are 3 answers

2
Nipu Chakraborty On

Here is an example:

import { useIdleTimer } from 'react-idle-timer' 

export const App = () => {
  const onPrompt = () => {
    // Fire a Modal Prompt
  }

  const onIdle = () => {
    // Close Modal Prompt
    // Do some idle action like log out your user
  }

  const onActive = (event) => {
    // Close Modal Prompt
    // Do some active action
  }

  const onAction = (event) => {
    // Do something when a user triggers a watched event
  }

  const {
    start,
    reset,
    activate,
    pause,
    resume,
    isIdle,
    isPrompted,
    isLeader,
    getTabId,
    getRemainingTime,
    getElapsedTime,
    getLastIdleTime,
    getLastActiveTime,
    getTotalIdleTime,
    getTotalActiveTime
  } = useIdleTimer({
    onPrompt,
    onIdle,
    onActive,
    onAction,
    timeout: 1000 * 60 * 20,
    promptTimeout: 0,
    events: [
      'mousemove',
      'keydown',
      'wheel',
      'DOMMouseScroll',
      'mousewheel',
      'mousedown',
      'touchstart',
      'touchmove',
      'MSPointerDown',
      'MSPointerMove',
      'visibilitychange'
    ],
    immediateEvents: [],
    debounce: 0,
    throttle: 0,
    eventsThrottle: 200,
    element: document,
    startOnMount: true,
    startManually: false,
    stopOnIdle: false,
    crossTab: false,
    name: 'idle-timer',
    syncTimers: 0,
    leaderElection: false
  })
  return (
    <HomePage />
  )
}```
1
Hashmat Ali Shah On
// How to implement in functional Component and are you using "react-idle- 
timer": "^4.2.9", then do this all

// IdleTimer states 
const idleTimer = () => {
    const [timeout, setTimeOut] = useState(1000 * 10 * 1)
    const [isTimedOut, setTimedOut] = useState(false)
    let idleTimer = HTMLElement | null;

    const onAction = (e) => {
        console.log('user did something', e)
        setTimedOut(false)
    }

    const onActive = (e) => {
        console.log('user is active', e)
        setTimedOut(false)
    }

    const onIdle = () => {
        debugger
        if (isTimedOut) {
            if (loginUserData.length > 0) {
                // Your SingOut function call here

            }
        } else {
            idleTimer?.reset()
            setTimedOut(true)
        }
        console.log("IdleTimer", idleTimer)

    }

    return (
        <>
            <IdleTimer
                ref={ref => { idleTimer = ref }}
                element={document}
                onActive={onActive}
                onIdle={onIdle}
                onAction={onAction}
                debounce={250}
                timeout={timeout}
            />
        </>
    )
}
export default idleTimer;
1
Muhammad Rohan On
import { useEffect, useState } from "react";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import ProtectedRoutes from "./utils/ProtectedRoutes";
import { useAppDispatch } from "./utils/hooks";
import Home from "./components/Home";
import Login from "./components/Login";
import Register from "./components/Register";
import NotFound from "./components/NotFound";
import AddTeamData from "./components/AddTeamData";
import Authenticate from "./components/Authenticate";
import TeamData from "./components/TeamData";
import { setUser } from './actions/authActions';
import './App.css';
import Verification from "./components/Verification";
import { useIdleTimer, IIdleTimer } from "react-idle-timer";
import ForgetPassword from "./components/ForgetPassword";

function App() {
  const dispatch = useAppDispatch();
  const token = localStorage.getItem("access_token");

  useEffect(() => {
    if (token) {`enter code here`
      dispatch(setUser());
    }
  }, [window.location.pathname, token]);

  const [state, setState] = useState<string>('Active');
  const [remaining, setRemaining] = useState<number>(0);

  const onIdle = () => {
    console.log('user is idle');
    setState('Idle');
    dispatch({ type: "LOGOUT" });
  };

  const onActive = () => {
    console.log('user is active');
    setState('Active');
  };

  const handleAction = (event?: Event, idleTimer?: IIdleTimer) => {
    if (remaining >= 40) {
      console.log("here" , event)
      return;
    } else {
      console.log("resetting");
      reset();
    }
    console.log('user did something', event);
  };

  const { getRemainingTime, reset } = useIdleTimer({
    onIdle,
    onActive,
    onAction: handleAction,
    timeout: 20 * 60 * 1000,
    throttle: 500,
  });

  useEffect(() => {
    const interval = setInterval(
      () => setRemaining(Number((getRemainingTime() / 1000).toFixed(0))),
      1000
    );
    return () => clearInterval(interval);
  }, [getRemainingTime]);

  useEffect(() => {
    if (localStorage.getItem('refresh_token') == null) {
      return;
    }
  }, []);

  return (
    <div>
      {remaining > 40 && (
        <div className="fixed w-full h-screen bg-gray-400 bg-opacity-80 flex justify-center items-center">
          <div className="bg-white opacity-100 p-5 rounded-lg flex flex-col justify-center items-center">
            <div className="text-center text-xl">
              <h1>You will be logged out in</h1>
              <h1 className="text-red-400">
                {Number(Math.floor(remaining / 60))}m : {remaining % 60}s{" "}
              </h1>
            </div>
            <p className="w-[80%] text-center py-3">
              You have been Inactive for some time. Do you want to continue
              using the site?
            </p>
            <div className="flex gap-4">
              <button className="h-9 px-3 rounded-full bg-green-400 text-white hover:bg-white hover:text-green-400 border border-green-400">
                Yes
              </button>
              <button className="h-9 px-3 rounded-full bg-red-400 text-white hover:bg-white hover:text-red-400 border border-red-400">
                No, Logout
              </button>
            </div>
          </div>
        </div>
      )}
      <BrowserRouter>
        <Routes>
          <Route path="/login" element={<Login />} />
          <Route path="/register" element={<Register />} />
          <Route path="/authenticate" element={<Authenticate />} />
          <Route path="/verification" element={<Verification />} />
          <Route path="/reset-password" element={<ForgetPassword />} />
          <Route element={<ProtectedRoutes />}>
            <Route path="/" element={<Home />} />
            <Route path="/team-data" element={<TeamData />} />
            <Route
              path="/add-team-data/:invitationId"
              element={<AddTeamData />}
            />
            <Route path="*" element={<NotFound />} />
          </Route>
        </Routes>
      </BrowserRouter>
    </div>
  );
}

export default App;