React Broadcast Channel Demo ✨
This is a demo page for the @nayaabh/react-broadcast-channel library. Open this page in multiple tabs or windows to see how messages are broadcasted between them.
How It Works
Steps to use the demo:
- Pop out this window in a new tab.
- Enter a message and choose a color for the message.
- Click on the "Publish" button to broadcast the message.
- The message will be displayed in all open windows or tabs, based on the color selected.

Code
Sample code for above example
demo-code.tsx
"use client";
import { useBroadcastState } from "@nayaabh/react-broadcast-channel";
import { useCallback, useEffect, useState } from "react";
import { FixedSizeList, ListChildComponentProps } from "react-window";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
const CHANNEL_NAME = "BroadcastChannel-001";
type MessageType = {
message: string;
color: string;
timeStamp: string;
};
export const BroadcastSandbox = () => {
const [message, setMessage] = useBroadcastState<MessageType>(CHANNEL_NAME);
const [logs, setLogs] = useState<MessageType[]>([]);
const onPublish = useCallback((e: any) => {
e.preventDefault();
const data = new FormData(e.target);
const text = data.get("message") as string;
const color = data.get("color") as string;
const dateTime = getTimestamp();
setMessage({ message: text, color, timeStamp: dateTime });
}, [setMessage]);
useEffect(() => {
if (message) {
setLogs((logs) => [message, ...logs]);
}
}, [message]);
return (
<div className="space-y-6">
<form onSubmit={onPublish} className="flex flex-col sm:flex-row gap-3">
<Input
name="message"
placeholder="Enter a message"
maxLength={100}
className="flex-1"
/>
<div className="flex items-center gap-2">
<input
type="color"
name="color"
defaultValue="#6b7280"
className="w-10 h-10 p-0 border-none bg-transparent cursor-pointer rounded-md overflow-hidden"
/>
<Button type="submit">
Publish
</Button>
</div>
</form>
<div className="w-full border rounded-md bg-muted/20 overflow-hidden shadow-sm">
<FixedSizeList
height={200}
width="100%"
itemSize={36}
itemCount={logs.length}
overscanCount={5}
>
{(props: ListChildComponentProps) => {
const { index, style } = props;
const { message, timeStamp, color } = logs[index] || {};
const log = `${timeStamp} - ${message}`;
return (
<div
key={index}
style={style}
className="px-4 py-2 border-b last:border-0 border-border/40 flex items-center text-xs font-mono"
>
<span style={{ color }} className="truncate">
{log}
</span>
</div>
);
}}
</FixedSizeList>
</div>
</div>
);
};
function getTimestamp() {
const date = new Date();
const year = date.getFullYear();
const month = `${date.getMonth() + 1}`.padStart(2, "0");
const day = `${date.getDate()}`.padStart(2, "0");
const hour = `${date.getHours()}`.padStart(2, "0");
const minute = `${date.getMinutes()}`.padStart(2, "0");
const second = `${date.getSeconds()}`.padStart(2, "0");
const millisecond = `${date.getMilliseconds()}`.padStart(2, "0");
return `${year}-${month}-${day} ${hour}:${minute}:${second}.${millisecond}`;
}