Send data between tabs in react app
Tags: react
Published: 2020-12-21 03:49:56

Yes! You can send data between different tabs or windows of your react app. Confusing hah?

Ok, let's assume you have made a [WebRTC](https://en.wikipedia.org/wiki/File:WebRTC_Logo.svg) app via [jitsi](https://jitsi.org/). The main goal of your app is video conferencing. Now you don't want any of your users to open two sessions at the same time in their browser for the calling. How can you do that? Here you can use the [Broadcast Channel API](https://developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API).

One other important thing is that this will only work only if your app/site is of the same [origin](https://developer.mozilla.org/en-US/docs/Glossary/origin).

---

Let's see that in action by an [example](https://gist.github.com/kamal-hossain/8a29c55099d0a100c65699bb0ddaf607).

# Create a react app

```bash
create-react-app browser-tab-broadcast-react
```

Start the app

```bash
npm start
```

# Modify the App.js file

Remove everything from your App.js file and paste these.

```js
import React from 'react'
import './App.css'

function App() {
  return (
    <div class="App">
      <h1> Something happening in the dom </h1>
    </div>
  )
}
export default App
```

All that we are doing is just rendering a div with an h1 tag.

```js
// ...
<h1> Something happening in the dom </h1>

<p>Only one tab could open at a time</p>
<button type="button" onClick={refreshPage}>
    <span>Reload</span>
</button>
```

Now this is the part where we want to show the user, if the page is already opnned in another tab or window of the same browser.

To do that we need a state to handle that. So that we can conditionally render the elements to the user.

```js
// ...
function App() {
  const [isOpnnedAlready, setIsOpnnedAlready] = React.useState(false)

  return (
    <div class="App">
// ...
```

By default, the state is `false` and that means this same page is not opened in another tab or window of the browser so we can put the condition in our JSX.

```js
// ...

function refreshPage() {
    window.location.reload()
}

 return (
    <div class="App">
      {!isOpnnedAlready ? (
        <h1>Something happening in the dom</h1>
      ) : (
        <>
          <p>Only one tab could open at a time</p>
          <button type="button" onClick={refreshPage}>
            <span>Reload</span>{' '}
          </button>
        </>
      )}
    </div>
// ...
```

So now, we need to listen for an event in our component. To see if another page is opened in another tab.

# Create a BroadcastChannel instance

For that, we need to create a channel in our app. Which will be available to all other tabs with the same protocol, origin, and port.

```js
// ...
const channel = React.useMemo(() => new BroadcastChannel('couldBeAnything'), [])
```

Here we have created a new `BroadcastChannel` instance and stored that in the channel variable. With this `couldBeAnything` name we are subscribing to a particular channel. By subscribing we are able to post and receive messages from it.

In extra we are using [useMemo](https://reactjs.org/docs/hooks-reference.html#usememo) hook to keep the instance value in memory. So that we don't have to re-run the code on every re-render.

# Sending and receiving data via BroadcastChannel

```js

const channel = React.useMemo(() => new BroadcastChannel('couldBeAnything'), [])

React.useEffect(() => {
    channel.postMessage({
      isOpnnedAlready: true,
    })
    channel.addEventListener('message', (e) => {
      setIsOpnnedAlready(e.data.isOpnnedAlready)
    })
    return channel.close
  }, [])

```

Here we are using [useEffect](https://reactjs.org/docs/hooks-reference.html#useeffect) hook. Here we are posting and receiving to the channel after every first render of the component.  

By calling `postMessage()` with our channel instance we are sending an object to the channel (here we can also send **string**, **array** etc). Right after that, we are calling `addEventListener()` to listen to the **message** event from the channel. And finally, we are closing the channel on component unmount. 

When all these things are done open up two tabs one after another, you will notice the changes on the page. The first tab will change its DOM whenever other tabs open in the same browser. 

![Demo](https://kamalhossain.me/gif/send-data-between-tabs.gif)

---

Resource(s): [1](https://dev.to/dcodeyt/send-data-between-tabs-with-javascript-2oa)