use-broadcast-channel
Exchange typed messages with other tabs, windows, and workers of the same origin through the Broadcast Channel API.
| Package | @vizejs/composable/use-broadcast-channel |
| Own the source | vize lib pull composable:use-broadcast-channel |
| Runtime exports | useBroadcastChannel |
| Gzip budget | 2048 B |
Minimal setup
Use a Vue 3.5+ project with Vue SFC compilation configured (see Vite+ integration).
vp install @vizejs/composable
Import the entry directly. Call lifecycle-bound utilities inside <script setup> so cleanup follows the component scope; consult the runtime contract for this entry's SSR and hydration behavior.
import { useBroadcastChannel } from "@vizejs/composable/use-broadcast-channel";
Try it
Tell other tabs that a draft changed
Send messages between tabs, windows and iframes of the same origin.
What to observe: Save in this tab delivers Draft saved at revision 3 to the second channel, which stands in for another tab.
A channel does not receive its own messages. Use validate to type-check incoming data from other tabs.
Compare the initial and interacted states


Copy the example
Save this complete SFC in your Vue project. Its public imports and source are the same ones executed in the preview.
<script setup lang="ts">
import { useBroadcastChannel } from "@vizejs/composable/use-broadcast-channel";
// Two channels with the same name stand in for two tabs of your app.
const editor = useBroadcastChannel<string>("docs-example-sync");
const otherTab = useBroadcastChannel<string>("docs-example-sync");
function publish() {
editor.post("Draft saved at revision 3");
}
</script>
<template>
<div class="composable-example">
<p>Tell other open tabs that a draft changed.</p>
<button type="button" @click="publish">Save in this tab</button>
<output aria-live="polite"
>Other tab received: {{ otherTab.data.value ?? "nothing yet" }}</output
>
</div>
</template>
Runtime contract
| Utility | Category | Stability | SSR | Hydration | Cleanup | Targets | Host globals | Uses |
|---|---|---|---|---|---|---|---|---|
useBroadcastChannel |
networking | experimental | deterministic-fallback | stable | caller, reactive-scope | web, desktop | MessageEvent, window |
tryOnScopeDispose |
API
useBroadcastChannel
Exchange typed messages with other tabs, windows, and workers of the same origin through the Broadcast Channel API. The channel follows the reactive name: changing it closes the old channel and opens a new one. The channel closes when the owning reactive scope stops or when close() is called; outside a scope the caller owns close(). Incoming payloads pass the validate type guard before they reach data, so foreign messages cannot widen the declared type. Server rendering: without a browser window no channel is opened (Node's global BroadcastChannel is ignored), supported is false, and post returns false. Inside a component the host is read after mounting, so hydration renders the server fallback first and never mismatches.
function useBroadcastChannel<Message>( name: MaybeRefOrGetter<string>, options: UseBroadcastChannelOptions<Message> = {}, ): BroadcastChannelControls<Message>
type Sync = { readonly type: "logout" };
const { data, post } = useBroadcastChannel<Sync>("auth");
post({ type: "logout" });
Types
BroadcastChannelLike
Minimal structural view of a BroadcastChannel instance.
| Member | Type | Description |
|---|---|---|
postMessage |
(message: unknown) => void |
Post a structured-cloneable message to every other channel with the same name. |
close |
() => void |
Close the channel; no further messages are delivered. |
BroadcastChannelHost
Capability host exposing a channel constructor; window satisfies it. The constructor is wrapped in an object because a bare class would be mistaken for a getter by MaybeRefOrGetter resolution.
| Member | Type | Description |
|---|---|---|
BroadcastChannel |
BroadcastChannelConstructor |
Channel constructor. |
BroadcastChannelFailure
Failure observed while using a broadcast channel.
| Member | Type | Description |
|---|---|---|
code |
BroadcastChannelErrorCode |
Which step failed. |
name |
string |
Channel name involved in the failure. |
cause |
unknown |
Exact thrown value, event, or rejected payload. |
UseBroadcastChannelOptions
Options for useBroadcastChannel.
| Member | Type | Description |
|---|---|---|
host? |
MaybeRefOrGetter<BroadcastChannelHost | null | undefined> |
Host exposing the channel constructor. null/undefined keeps the composable closed, which is also what happens during server rendering. |
validate? |
(data: unknown) => data is Message |
Validate incoming payloads. Rejected payloads leave data untouched and report an "invalid-message" failure. |
onMessage? |
(message: Message) => void |
Observe every accepted message. |
onError? |
(failure: BroadcastChannelFailure) => void |
Observe failures. Failures never throw out of the composable. |
BroadcastChannelControls
Reactive state and controls returned by useBroadcastChannel.
| Member | Type | Description |
|---|---|---|
data |
Readonly<ShallowRef<Message | undefined>> |
Most recent accepted message received from another context. |
supported |
Readonly<Ref<boolean>> |
Whether a channel constructor is available. |
closed |
Readonly<Ref<boolean>> |
Whether no channel is currently open. |
error |
Readonly<ShallowRef<BroadcastChannelFailure | undefined>> |
Most recent failure, cleared by the next successful post or message. |
post |
(message: Message) => boolean |
Post a typed message. |
close |
() => void |
Close the channel and stop following the reactive name. Idempotent. |