Special Offer: Free website in return for featuring your site!

Browser Tab State Synchronization with React hooks

In a web app, there's many times its useful to keep app state synchronized across browser tabs. The method described here uses the browser's localStorage API which is supported in most modern browsers. This allows tabs from web pages on the same domain to be able to talk to each other locally without communicating through a server.

This is just one way of doing this. Some other ways of doing this include cookie based synchronization, which is basically the same thing but we just read / write from cookies.

The gist of how this is done is the following snippets responsible for accessing the browser's local storage API:

window.addEventListener("storage", event => {
  // This is fired whenever another tab writes something to localStorage
})

// Current tab writes to local storage
localStorage.setItem("key", "test")

Now applying this to a simple react component:

/ ComponentReadsFromLocalStorage.js

import React, { useState, useEffect } from "react"

// This is the key we use to communicate between tabs
const UNIQUE_STORAGE_KEY = "unique_key"

function ComponentReadsFromLocalStorage() {
  const [counter, setCounter] = useState(0)

  // Hook that receives updates from other tabs
  useEffect(() => {
    function onStorageUpdate(event) {
      if (event.key !== UNIQUE_STORAGE_KEY || Number.isNaN(event.newValue)) {
        return
      }

      setCounter(Number(event.newValue))
    }
    window.addEventListener("storage", onStorageUpdate)

    return function cleanup() {
      window.removeEventListener("storage", onStorageUpdate)
    }
  })

  return (
    <div>
      <button
        onClick={() => {
          const newCounter = counter + 1
          // Update current tab state
          setCounter(newCounter)

          // Update other tabs' state
          localStorage.setItem(UNIQUE_STORAGE_KEY, newCounter)
        }}
      >
        Counter
      </button>
      {counter}
    </div>
  )
}

export default ComponentReadsFromLocalStorage

Note that there isn't any error handling done here, there is a chance that localStorage.setItem may fail due to lack of storage space, or perhaps the localStorage API may not exist for older browsers so you should be handling these for production apps

Get in Touch!

Special Offer to build you a website for free. Note this doesn't include hosting or custom domains you may want to use. All I ask for in return is to be able to feature your site as a testimonial.

Let me know about your business, what your budget is, and the idea you have in mind. I'm always looking to work with great clients :)