DEV Community

loading...
Uclusion

Multiple tabs in your app

uclusion profile image David Israel ・2 min read

We had some problems with multiple tabs that are pretty common:

  • Writing to storage could collide or not get picked up
  • Logout in one tab would not be noticed in the other
  • Sync with the backend would be done independently by all

Being Uclusion we of course used a Uclusion Dialog to decide and the options were:

Pretty easy decision because in addition to using broadcast channel API when available the NPM package supported leader selection. That allowed us to set up a React context to let us know anywhere in the code whether our tab was leader or not - see code here.

We could also send messages to the other tabs telling them to refresh from IndexedDB like so

const myChannel = new BroadcastChannel(COMMENTS_CHANNEL);
      return myChannel.postMessage('comments').then(() => myChannel.close())
        .then(() => console.info('Update comment context sent.'));
Enter fullscreen mode Exit fullscreen mode

Now the basic idea we followed was the leader syncs from the backend and stores in an IndexedDB namespace and all other tabs store their local edits in a differently named IndexedDB namespace. Its very unlikely more than one tab is doing local edits at a time and even if somehow they were the sync from the network is the eventual master.

Also very simple logout broadcasts a message which is listened for by the other tabs here

const [logoutChannel, setLogoutChannel] = useState(undefined);

  useEffect(() => {
    console.info('Setting up logout channel');
    const myLogoutChannel = new BroadcastChannel('logout');
    myLogoutChannel.onmessage = () => {
      console.info('Logging out from message');
      onSignOut().then(() => console.info('Done logging out'));
    }
    setLogoutChannel(myLogoutChannel);
    return () => {};
  }, []);
Enter fullscreen mode Exit fullscreen mode

Discussion

pic
Editor guide