Getting Started
react-broadcast-sync syncs UI state and user events between browser tabs of the same origin in React apps. It wraps the native BroadcastChannel API in a hook and an optional provider.
This guide walks you from an empty file to two tabs staying in sync, step by step.
1. Install
Section titled “1. Install”npm install react-broadcast-syncThe package declares React and React DOM >=16.8.0 as peer dependencies. The package ships ESM, CJS, and TypeScript types.
2. Pick your entry point
Section titled “2. Pick your entry point”There are two ways to open a channel. Pick one per app (or per part of an app):
- The hook -
useBroadcastChannel(name, options)opens a channel inside one component. Call it once per channel. Best for most apps. - The provider -
<BroadcastProvider>opens one channel at the top of a subtree and shares it through context withuseBroadcastProvider(). Best when many components share one channel.
Both return the same actions (messages, postMessage, ping, and friends). The steps below use the hook; the provider version is covered in Use the provider.
3. Open a channel
Section titled “3. Open a channel”import { useBroadcastChannel } from 'react-broadcast-sync';
function Counter() { const counter = useBroadcastChannel('counter'); // ...}Every tab that opens a channel with the same name hears the others. A tab never receives its own messages.
4. Send a message
Section titled “4. Send a message”postMessage(type, content) sends to every other tab with the channel open. type is a label you choose; content is anything serializable.
counter.postMessage('increment', { by: 1 });5. Receive and render
Section titled “5. Receive and render”Incoming messages land in messages, an event log of BroadcastMessage objects. For a counter, keep the count as local state and handle each incoming increment with onMessage. Apply your own click locally too, because the sender never receives its own message:
import { useState } from 'react';import { useBroadcastChannel } from 'react-broadcast-sync';
export default function Counter() { const [count, setCount] = useState(0); const { postMessage } = useBroadcastChannel('counter', { registeredTypes: ['increment'], onMessage: { increment: () => setCount(current => current + 1), }, });
const increment = () => { setCount(current => current + 1); postMessage('increment', { by: 1 }); };
return <button onClick={increment}>Count: {count}</button>;}Two things to keep in mind:
messagesis a log, not current state.keepLatestMessage: truekeeps only the newest received message; it does not accumulate increments or replay history.- A tab that opens late does not receive messages from before it opened.
6. See it sync
Section titled “6. See it sync”Open the page in a second tab (same browser, same origin) and click the button. While both tabs are listening, both count every click: the clicked tab updates locally and the other handles the incoming increment. A new or refreshed tab starts at 0; this example does not restore earlier clicks.
7. Next steps
Section titled “7. Next steps”- Use the hook - options, patterns, and multiple channels
- Use the provider - share one channel through context
- Tutorial: build the counter demo - a full walkthrough that ends in a working demo app
- Try the live demos: hook demo and provider demo
