import {
getValueFromLocalStorage,
localStorageKeys,
removeValuesFromLocalStorage,
saveValueToLocalStorage,
} from "@/utils/local-storage";
import { TFunction } from "@/types";
import { useEffect, useRef, useState } from "react";
interface UseIdleTimer {
debounce?: number; // Delay until function calls after user becomes inactive
onIdle?: TFunction; // Function to call when a user becomes inactive
onActive?: TFunction; // Function to call when a user becomes active
TTL?: number; // Time to live, number of minutes after which user will be considered inactive
}
/**
* `useIdleTimer` is a React hook to track user activity and time of inactivity.
* It provides several configuration options as arguments and returns a boolean indicating whether the user is currently inactive.
* returns object containing boolean indicating whether the user is currently inactive
*/
const useIdleTimer = ({
onIdle,
onActive,
debounce,
TTL = 2,
}: UseIdleTimer) => {
const [isIdle, setIsIdle] = useState(false);
const intervalRef = useRef<NodeJS.Timeout | null>(null);
const eventsToListen = ["click", "mousemove", "keypress", "scroll"];
const clearLastActivityTime = () => {
removeValuesFromLocalStorage(localStorageKeys.LAST_ACTIVITY_TIME);
};
// Checks for user inactivity based on last activity timestamp
const checkForUserInactivity = () => {
const currentTime = Date.now();
// Fetch last activity timestamp from localstorage
const lastActivityTime = parseInt(
getValueFromLocalStorage(localStorageKeys.LAST_ACTIVITY_TIME, "0")
);
// Calculate difference in minutes
const diffInMs: number = currentTime - lastActivityTime;
const diffInMinutes: number = diffInMs / (1000 * 60);
// Check if the difference in minutes is bigger or equal to TTL
if (diffInMinutes >= TTL) {
clearLastActivityTime();
if (onIdle) {
onIdle();
setIsIdle(true);
}
}
};
const checkLastActivityTimeExistence = (): boolean => {
const lastActivityTime = getValueFromLocalStorage(
localStorageKeys.LAST_ACTIVITY_TIME
);
return !!lastActivityTime;
};
/**
* Updates last activity timestamp in localstorage and executes the provided
* onActive function whenever a registered event occurs
*/
const updateLastActivityTime = () => {
saveValueToLocalStorage(
localStorageKeys.LAST_ACTIVITY_TIME,
`${Date.now()}`
);
if (onActive) {
onActive();
}
};
const startTrackingUserActivity = () => {
eventsToListen.forEach((event) => {
window.addEventListener(event, updateLastActivityTime);
});
};
const stopTrackingUserActivity = () => {
eventsToListen.forEach((event) => {
window.removeEventListener(event, updateLastActivityTime);
});
clearLastActivityTime();
};
// Start an interval that checks for user inactivity every debouncing millisecond
useEffect(() => {
intervalRef.current = setInterval(() => {
checkForUserInactivity();
}, debounce ?? 30000);
// Clean up the interval on component unmount
return () => {
if (intervalRef.current) {
clearInterval(intervalRef.current);
}
};
}, []);
// If a user is already idle, stop tracking user activity
useEffect(() => {
if (isIdle) {
if (intervalRef.current) {
clearInterval(intervalRef.current);
}
}
}, [isIdle]);
/**
* This effect is triggered on component mount.
* It checks if there is a recorded "last active time" in the local storage.
* If it exists, the function `checkForUserInactivity` is called to determine the duration of the user's inactivity.
* */
useEffect(() => {
if (checkLastActivityTimeExistence()) {
checkForUserInactivity();
}
}, []);
// Sets up the user activity tracking
useEffect(() => {
updateLastActivityTime();
startTrackingUserActivity();
// Clean up the listeners on component unmount
return () => {
stopTrackingUserActivity();
};
}, []);
return { isIdle };
};
export default useIdleTimer;
// example on how to use it
useIdleTimer({
onIdle: signOut,
debounce: 10000,
TTL: 0.5,
});
Last active
September 1, 2023 04:25
-
-
Save Bonny-kato/ae0213f0acbbb4c59fcf9d7352a31441 to your computer and use it in GitHub Desktop.
React hook called `useIdleTimer` that tracks user activity and determines if the user is currently inactive. It takes in several configuration options as arguments and returns an object containing a boolean value indicating whether the user is currently inactive.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment