UNPKG

@rtcio/react

Version:

A wrapper around the @rtcio/core library for React integration

70 lines 2.95 kB
import { useContext, useEffect, useRef } from "react"; import { p2pContext } from "../Provider"; import { option } from "@dbidwell94/ts-utils"; /** * This function will create a typed usePeerListener hook * which will allow strongly typed event subscriptions */ export function createUsePeerListener() { function usePeerListener(event, callback, onlyPeerId) { const ctx = useContext(p2pContext); if (!ctx) { throw new Error("usePeerListener must be called in a P2PProvider"); } const { peerIds, peers } = ctx; const subscribedPeers = useRef(new Map()); const callbackRef = useRef(callback); useEffect(() => { callbackRef.current = callback; }, [callback]); useEffect(() => { const subs = subscribedPeers.current; const currentPeerIds = new Set(peerIds); // 1. Clean up stale subscriptions. // This runs for peers that have left OR if the event name has changed. for (const [peerId, sub] of subs.entries()) { if (!currentPeerIds.has(peerId) || sub.eventName !== event || (onlyPeerId && peerId !== onlyPeerId)) { sub.controller.abort(); subs.delete(peerId); } } const iterable = option .unknown(onlyPeerId) .andThen((val) => { if (peers.current.get(val)) { return option.some([ val, peers.current.get(val), ]); } return option.none(); }) .map(([peerId, conn]) => new Map([[peerId, conn]]).entries()) .unwrapOr(peers.current.entries()); // 2. Add subscriptions for new peers. for (const [peerId, peer] of iterable) { // If a subscription for this peer doesn't already exist, create one. if (!subs.has(peerId)) { const controller = new AbortController(); // The handler always calls the latest callback from the ref. const handler = (...args) => callbackRef.current(peerId, ...args); peer.on(event, handler, controller.signal); subs.set(peerId, { eventName: event, controller }); } } }, [peerIds, event, onlyPeerId]); // 3. When component unmounts, clean up all subscriptions useEffect(() => { return () => { for (const [peerId, sub] of subscribedPeers.current.entries()) { sub.controller.abort(); subscribedPeers.current.delete(peerId); } }; }, []); } return usePeerListener; } //# sourceMappingURL=usePeerListener.js.map