DEV Community

Mayank Gupta
Mayank Gupta

Posted on

Syncing Multiple Tabs in a Browser Application

If you open the same application in multiple tabs on the same browser, sometimes it becomes really important to keep these tabs in sync. For example, think about your online banking portal. If you log in on one tab and then try to open the same portal in another tab, the first tab will often show a “session expired” message or automatically log you out.

That's a classic case of tab synchronization.

The problem I faced

In my case, the issue was auth syncing.

When the application was opened in multiple tabs, if the user logged out in one tab, the other tabs still tried to use the expired access token. Since the token was no longer valid, all API calls in those tabs failed until the user manually refreshed.

The solution

The idea is simple:

  1. Use localStorage as a shared state between tabs (since it is accessible across all the tabs of the same origin).
  2. Keep a special key (let's call it changeInAuth) in localStorage that updates whenever login or logout happens.
  3. In every tab, listen for changes to this key using the storage event. When a change is detected, clear any invalid data from sessionStorage and reload the page so that the tabs fetches fresh tokens and user data.

Step 1: Add a storage event listener in App.tsx

useEffect(() => {
  const handleLocalStorageChange = (event: StorageEvent) => {
    // Check if the auth key changed
    if (event.key === "changeInAuth") {
      // Clear session data
      sessionStorage.clear();

      // Refresh the page
      window.location.reload();
    }
  };

  window.addEventListener("storage", handleLocalStorageChange);

  // Always clean up event listeners
  return () => {
    window.removeEventListener("storage", handleLocalStorageChange);
  };
}, []);

Enter fullscreen mode Exit fullscreen mode

Here, we're telling the browser:

"If any tab updates the changeInAuth key in localStorage, reload this tab."

Step 2: Update localStorage during login

const login = async (userCreds) => {
  try {
    // Call authentication API
    // Save tokens, user info, etc. in sessionStorage or cookies

    // Trigger sync event for other tabs
    localStorage.setItem("changeInAuth", Date.now().toString());
  } catch (error) {
    console.error("Login failed:", error);
  }
};
Enter fullscreen mode Exit fullscreen mode

Step 3: Update localStorage during logout

const logout = async () => {
  // Call logout API
  // Clear tokens, user info, and sessionStorage/cookies

  // Trigger sync event for other tabs
  localStorage.setItem("changeInAuth", Date.now().toString());
};
Enter fullscreen mode Exit fullscreen mode

How it works

  • Whenever login or logout happens, a unique timestamp is stored in localStorage under the key changeInAuth.
  • All tabs are listening for changes to this key.
  • When a change is detected, tabs clear old session data and reload.
  • After reload, they fetch fresh tokens and sync with the backend.

This way, the application can:

  1. Keep all tabs sync.
  2. Handle single-user sessions properly
  3. Automatically switch to the correct user when someone logs in/out.

Final thoughts

The storage event is a very handy browser feature, and in many cases, a few lines of code are enough to solve what could otherwise be a very frustrating problem.

Top comments (0)