UNPKG

@fishjam-cloud/react-client

Version:
88 lines (87 loc) 2.99 kB
import { useCallback, useContext, useEffect, useState } from "react"; import { FishjamClientContext } from "../contexts/fishjamClient"; import { PeerStatusContext } from "../contexts/peerStatus"; import { useCurrentCallback } from "./internal/useCurrentCallback"; /** * Hook for data channel operations - publish and subscribe to data. * * @category Connection * @group Hooks */ export function useDataChannel() { const fishjamClientRef = useContext(FishjamClientContext); const peerStatus = useContext(PeerStatusContext); if (!fishjamClientRef) throw Error("useDataPublisher must be used within FishjamProvider"); const client = fishjamClientRef.current; const [ready, setReady] = useState(false); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); useEffect(() => { const publisherReady = client.getDataChannelsReadiness(); setReady(publisherReady); const handleReady = () => { setReady(true); setError(null); }; const handleDisconnect = () => { setReady(false); }; const handleError = (err) => { setReady(false); setLoading(false); setError(err); }; client.on("dataChannelsReady", handleReady); client.on("dataChannelsError", handleError); client.on("disconnected", handleDisconnect); return () => { client.removeListener("dataChannelsReady", handleReady); client.removeListener("disconnected", handleDisconnect); }; }, [client]); // Stable identity with a live closure: peerStatus / loading / ready must be // observed at call time so a captured reference doesn't reject with a stale // "Peer is not connected" right after the connect promise settles. const initialize = useCurrentCallback(async () => { if (loading || ready) return; if (peerStatus !== "connected") { setError(new Error("Peer is not connected")); return; } try { setLoading(true); await client.createDataChannels(); } catch (err) { if (err instanceof Error) { setError(err); } } finally { setLoading(false); } }); const publishData = useCallback((data, options) => { try { client.publishData(data, options); } catch (err) { if (err instanceof Error) { setError(err); } } }, [client]); const subscribeData = useCallback((callback, options) => { return client.subscribeData(callback, options); }, [client]); return { publishData, subscribeData, initializeDataChannel: initialize, dataChannelReady: ready, dataChannelLoading: loading, dataChannelError: error, }; }