UNPKG

rooks

Version:

Collection of awesome react hooks

86 lines (84 loc) 2.28 kB
// src/hooks/useBroadcastChannel.ts import { useCallback, useEffect, useMemo, useRef } from "react"; function isEventLike(error) { return error instanceof Event || error instanceof Error; } function useBroadcastChannel(channelName, options) { const { onMessage, onError } = options || {}; const isSupported = useMemo(() => { return typeof window !== "undefined" && typeof BroadcastChannel !== "undefined"; }, []); const channelRef = useRef(null); const stableOnMessage = useCallback( (event) => { if (onMessage) { onMessage(event.data); } }, [onMessage] ); const stableOnError = useCallback( (event) => { if (onError) { onError(event); } }, [onError] ); useEffect(() => { if (!isSupported) { return; } try { const channel = new BroadcastChannel(channelName); channelRef.current = channel; channel.addEventListener("message", stableOnMessage); channel.addEventListener("messageerror", stableOnError); return () => { channel.removeEventListener("message", stableOnMessage); channel.removeEventListener("messageerror", stableOnError); channel.close(); channelRef.current = null; }; } catch (error) { if (onError && isEventLike(error)) { onError(error); } } }, [channelName, isSupported, stableOnMessage, stableOnError, onError]); const postMessage = useCallback( (data) => { if (!isSupported) { console.warn("useBroadcastChannel: BroadcastChannel API is not supported"); return; } if (!channelRef.current) { console.warn("useBroadcastChannel: Channel is not initialized"); return; } try { channelRef.current.postMessage(data); } catch (error) { console.error("useBroadcastChannel: Failed to post message", error); if (onError && isEventLike(error)) { onError(error); } } }, [isSupported, onError] ); const close = useCallback(() => { if (channelRef.current) { channelRef.current.close(); channelRef.current = null; } }, []); return { postMessage, close, isSupported }; } export { useBroadcastChannel };