Cross Tab Communication with Javascript
Tags: javascript, react, webdev
Published: 2019-12-27 02:13:32

About a month ago an interesting problem came up at work, how can I listen to a form being submitted that may be in another tab? It's something that if it was in the same tab, would be much more straight forward. But I also wanted to know can I send messages between these two, or more, tabs.

# What is Cross Tab Communication?

Cross Tab Communication is the ability of multiple tabs, windows, frames of iframes (further known as an instance) to send and receive 'messages' to and from other instances.

# Limitations / Gotchas

This does come with some drawbacks. This will only work with domains on the same-origin.

You will not be able to use this across HTTP and HTTPS.
You will not be able to use this across different hosts.
You will not be able to use this across different ports.

# How is this useful?

Before getting into some demos, I figure I would go over why this can be useful. Sometimes your users are going to have multiple instances of your site open, and how we handle their experience can be quite important. 

For example, Dan Abramov's blog https://overreacted.io/ has a toggle for a dark mode/light mode. Using this, you could switch all open instances to the preferred theme without refreshing.

# Examples / Demos

### Example 1 - LocalStorage

[External link if you don't want the preview](https://klpei.csb.app/)

{% codesandbox session-storage-example-1-klpei %}
{% codesandbox session-storage-example-1-klpei %}

How this works is by setting/modifying a value in local storage or session storage on load of the application. When this happens, an event is fired that can be listened to on any other instance. This event contains information such as the key that was modified, the previous value, the new value and much more. If you're familiar with React, this is similar to how you can compare the previous props, to the current props in class lifecycle method componentDidUpdate.

#### Drawbacks of Example 1

There are some draw backs to using this method. For one, you can not store objects in local storage/session storage unless they are stringified. This means you would have to parse any of these values which may not be a huge deal, but in my opinion is not ideal. 

The second draw back is that the event will not be fired if a value is updated to the same value. In my example I get around that limitation to setting the key `loaded` to Date.now().

### Example 2 - BroadcastChannel

[External link if you don't want the preview](https://qckg2.csb.app/)

{% codesandbox broadcastchannel-message-demo-1-qckg2 %}
{% codesandbox broadcastchannel-message-demo-1-qckg2 %}

In this example, I'm using the BroadcastChannel API. To do this, you create a new BroadcastChannel using a name (Similar to an IRC channel).

After subscribing to the channel you are returned an instance of the BroadcastChannel object, which in this example we use two parts of. You can send a message using the `postMessage` function, or attach a function to the `onmessage` property.

Similar with Example 1, and messages you send in one instance will be received in other instances. Along with the ability to subscribe to the same channel multiple times.

#### Drawbacks/Benefits of Example 2

Unlike Example 1, you are able to post full objects, arrays and other pieces of data.

However, Example 2 is a little bit more complicated and may be overkill depending on what you're trying to do.

Support for the BroadcastChannel API is also limited. Compared to local storage (globally at 92%), BroadcastChannel is at almost 76%. Chrome and Firefox both support it, with no support from IE, Safari and Edge. (Chromium Edge does support it, but is still considered in Beta as of this post).

# More Usecases

This could be used in a CMS to let the user know they already have an instance open when trying to modify something, or to keep it in sync across tabs.

Authentication/locked content could be unlocked when logging in so that other windows are not out of sync.

Changing a profile picture

Communication between iframes.

Changing themes of a website, and syncing those changes across all tabs. 


# Conclusion

I don't think that this is going to be ground breaking and change the way we make our applications. But I do think implementing this across some features of our applications could improve the user experience. 

If you have any other use cases you think this would be useful for, I'd love to hear it!

# Resources

[CanIUse - Localstorage](https://caniuse.com/#feat=mdn-api_window_localstorage)
[CanIUse - BroadcastChannel](https://caniuse.com/#feat=broadcastchannel)
[MDN - BroadcastChannel](https://developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API)