javascript - Handling sessions and idle timer between multiple tabs in a React SPA - Stack Overflow

admin2025-04-20  1

I'm developing a React application that has user authentication with session duration. While login, the response will give session duration with userObject. I'm persisting the loggedUser object using redux-persist in localStorage. I used react-idle-timer to detect the tab idle with sessionDuration I'm getting in loggedUser Object. when user idle reached timeout then, I'll clear the localStorage results user logout.

Here is the Issue I'm facing:

The flow is working exactly for the single tab. when user uses multiple tab. For example, I'm opening a page in the second tab, loggedUser data will be shared using localStorage, here I'm actively using the page. but the first tab gets idle and when the duration exceeds the first tab will be loggedOut by clearing the localStorage, the user who uses second tab actively will be forced to logout, since there is no loggedUser data (localStorage).

How can I handle this?

I'm developing a React application that has user authentication with session duration. While login, the response will give session duration with userObject. I'm persisting the loggedUser object using redux-persist in localStorage. I used react-idle-timer to detect the tab idle with sessionDuration I'm getting in loggedUser Object. when user idle reached timeout then, I'll clear the localStorage results user logout.

Here is the Issue I'm facing:

The flow is working exactly for the single tab. when user uses multiple tab. For example, I'm opening a page in the second tab, loggedUser data will be shared using localStorage, here I'm actively using the page. but the first tab gets idle and when the duration exceeds the first tab will be loggedOut by clearing the localStorage, the user who uses second tab actively will be forced to logout, since there is no loggedUser data (localStorage).

How can I handle this?

Share Improve this question edited Dec 6, 2022 at 22:36 Peter Mortensen 31.6k22 gold badges110 silver badges133 bronze badges asked Mar 13, 2021 at 17:24 Mohammed IsmailMohammed Ismail 3081 gold badge4 silver badges15 bronze badges 1
  • Check if this helps you - blog.guya/2015/06/12/… – Diwakar Singh Commented Mar 13, 2021 at 18:07
Add a ment  | 

5 Answers 5

Reset to default 2

Yeah... At the beginning I was facing the same issue. You're not alone, dear. Just add the crossTab property to the code and your problem will be solved.

<div>
  <IdleTimer
    crossTab={true}
    ref={idleTimerRef}
    timeout={1000 * 60 * sessionTimeoutPeriod}
    onIdle={onIdle}></IdleTimer>
</div>

You can set the crossTab property in the IdleTimer ponent to true.

<IdleTimer
  crossTab={true}
  ref={idleLogoutRef}
  timeout={timeOutLogin * 60 * 1000}
  onIdle={logoutUser}
  onActive={stayActive}
></IdleTimer>

If not using a library, you can subscribe to on change events in local storage and refresh the page.

Example:

window.addEventListener( 'storage', function ( event ) {
    console.log( event.key );
    if ( event.key === 'user_logout' ) {
        window.location.reload();
    }
} );

The event does not fire on the tab that is making the change, but it fires on the rest of the domain's tabs in the browser.

You can make use of isLastActiveTab callback func of the API, so that the onIdle Callback will be executed only if the last active tab is going Idle:

//useIdleTimeout.js

const useIdleTimeout = ({promptBeforeIdle, idleTime = 1}) => {

  const idleTimeout = 1000 * idleTime;
  const dispatch = useDispatch();

  const {isLoggedIn} = useSelector(state => state.login);

  const handleIdle = () => {
    if(isLoggedIn && idleTimer.isLastActiveTab()) {
     // Logout Logic goes here
      axios.post('/logout').then((res) => dispatch(logout())).catch(err => console.error(err));
    }
  }

  const handleTabFocus = () => {
    idleTimer.reset();
  }

  useEffect(() => {
    window.addEventListener('focus', handleTabFocus);
    return() => {
      window.removeEventListener('focus', handleTabFocus);
    }
  },[]);

  const idleTimer = useIdleTimer({
    crossTab: true,
    timeout: idleTimeout,
    promptBeforeIdle: idleTimeout / 2,
    onPrompot: onIdle,
    onIdle: handleIdle,
    debounce: 500
  });

  return {
    idleTimer
  }
}

export default useIdleTimeout;

In the example above i have assumed that you are storing 'isLoggedIn' variable in your redux store, to make sure that the user is logged in before performing the logout.

In your HomePage or App Component :

const App = () => {
 
 const handleBeforeIdle = () => {
   alert('Notify User, he is about to be Idle');
 }

 const {idleTimer} = useIdleTimeout(promptBeforeIdle: handleBeforeIdle, idleTime: 10});

return (
 // ...
)
}

Note that this solution resolves two issues with cross Tabs Idle timeout: 1- Prevent the onIdle() callback function if the user is active on at least one tab, and inactive on the others. 2- onIdle() will be executed only once, by the last active tab.

I set crossTab as 'true' but it did not work until I added 'syncTimers' property

useIdleTimer({
onIdle,
timeout: 1 * 60 * 1000,
crossTab: true,
throttle: 1000,
syncTimers: 200});
转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1745121018a286146.html

最新回复(0)