use-broadcast-channel
Version:
React hooks for accessing web broadcast channel.
112 lines • 4.99 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.useBroadcastState = exports.useBroadcastChannel = void 0;
const React = __importStar(require("react"));
/**
* React hook to create and manage a Broadcast Channel across multiple browser windows.
*
* @param channelName Static name of channel used across the browser windows.
* @param handleMessage Callback to handle the event generated when `message` is received.
* @param handleMessageError [optional] Callback to handle the event generated when `error` is received.
* @returns A function to send/post message on the channel.
* @example
* ```tsx
* import {useBroadcastChannel} from 'react-broadcast-channel';
*
* function App () {
* const postUserIdMessage = useBroadcastChannel('userId', (e) => alert(e.data));
* return (<button onClick={() => postUserIdMessage('ABC123')}>Send UserId</button>);
* }
* ```
* ---
* Works in browser that support Broadcast Channel API natively. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API#browser_compatibility).
* To support other browsers, install and use [broadcastchannel-polyfill](https://www.npmjs.com/package/broadcastchannel-polyfill).
*/
function useBroadcastChannel(channelName, handleMessage, handleMessageError) {
const [channel] = React.useState(typeof window !== "undefined" && "BroadcastChannel" in window
? new BroadcastChannel(channelName)
: null);
useChannelEventListener(channel, "message", handleMessage);
useChannelEventListener(channel, "messageerror", handleMessageError);
return React.useCallback((data) => channel?.postMessage(data), [channel]);
}
exports.useBroadcastChannel = useBroadcastChannel;
/**
* React hook to manage state across browser windows. Has the similar signature as `React.useState`.
*
* @param channelName Static name of channel used across the browser windows.
* @param initialState Initial state.
* @returns Tuple of state and setter for the state.
* @example
* ```tsx
* import {useBroadcastState} from 'react-broadcast-channel';
*
* function App () {
* const [count, setCount] = useBroadcastState('count', 0);
* return (
* <div>
* <button onClick={() => setCount(prev => prev - 1)}>Decrement</button>
* <span>{count}</span>
* <button onClick={() => setCount(prev => prev + 1)}>Increment</button>
* </div>
* );
* }
* ```
* ---
* Works in browser that support Broadcast Channel API natively. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API#browser_compatibility).
* To support other browsers, install and use [broadcastchannel-polyfill](https://www.npmjs.com/package/broadcastchannel-polyfill).
*/
function useBroadcastState(channelName, initialState) {
const [isPending, startTransition] = React.useTransition();
const [state, setState] = React.useState(initialState);
const broadcast = useBroadcastChannel(channelName, (ev) => setState(ev.data));
const updateState = React.useCallback((input) => {
setState((prev) => {
const newState = typeof input === "function" ? input(prev) : input;
startTransition(() => broadcast(newState));
return newState;
});
}, [broadcast]);
return [state, updateState, isPending];
}
exports.useBroadcastState = useBroadcastState;
// Helpers
/** Hook to subscribe/unsubscribe from channel events. */
function useChannelEventListener(channel, event, handler) {
const callbackRef = React.useRef(handler);
if (callbackRef.current !== handler) {
callbackRef.current = handler;
}
React.useEffect(() => {
const callback = callbackRef.current;
if (!channel || !callback) {
return;
}
channel.addEventListener(event, callback);
return () => channel.removeEventListener(event, callback);
}, [channel, event]);
}
//# sourceMappingURL=index.js.map