UNPKG

partysocket

Version:
131 lines (126 loc) 4.08 kB
import { r as ReconnectingWebSocket } from "./ws-iUSOdHtT.js"; import { useEffect, useMemo, useRef, useState } from "react"; //#region src/use-handlers.ts /** Attaches event handlers to a WebSocket in a React Lifecycle-friendly way */ const useAttachWebSocketEventHandlers = (socket, options) => { const handlersRef = useRef(options); handlersRef.current = options; useEffect(() => { const onOpen = (event) => handlersRef.current?.onOpen?.(event); const onMessage = (event) => handlersRef.current?.onMessage?.(event); const onClose = (event) => handlersRef.current?.onClose?.(event); const onError = (event) => handlersRef.current?.onError?.(event); socket.addEventListener("open", onOpen); socket.addEventListener("close", onClose); socket.addEventListener("error", onError); socket.addEventListener("message", onMessage); return () => { socket.removeEventListener("open", onOpen); socket.removeEventListener("close", onClose); socket.removeEventListener("error", onError); socket.removeEventListener("message", onMessage); }; }, [socket]); }; //#endregion //#region src/use-socket.ts /** When any of the option values are changed, we should reinitialize the socket */ const getOptionsThatShouldCauseRestartWhenChanged = (options) => [ options.startClosed, options.minUptime, options.maxRetries, options.connectionTimeout, options.maxEnqueuedMessages, options.maxReconnectionDelay, options.minReconnectionDelay, options.reconnectionDelayGrowFactor, options.debug ]; /** * Initializes a PartySocket (or WebSocket) and keeps it stable across renders, * but reconnects and updates the reference when any of the connection args change. */ function useStableSocket({ options, createSocket, createSocketMemoKey: createOptionsMemoKey }) { const { enabled = true } = options; const socketOptions = useMemo(() => { return options; }, [createOptionsMemoKey(options)]); const [socket, setSocket] = useState(() => createSocket({ ...socketOptions, startClosed: true }) ); const socketInitializedRef = useRef(null); const createSocketRef = useRef(createSocket); createSocketRef.current = createSocket; const prevEnabledRef = useRef(enabled); const prevSocketOptionsRef = useRef(socketOptions); useEffect(() => { const optionsChanged = prevSocketOptionsRef.current !== socketOptions; prevSocketOptionsRef.current = socketOptions; if (!enabled) { socket.close(); prevEnabledRef.current = enabled; return; } if (!prevEnabledRef.current && enabled) { socket.reconnect(); prevEnabledRef.current = enabled; return; } prevEnabledRef.current = enabled; if (socketInitializedRef.current === socket) if (optionsChanged) setSocket( createSocketRef.current({ ...socketOptions, startClosed: false }) ); else { if (socketOptions.startClosed !== true) socket.reconnect(); return () => { socket.close(); }; } else { if (!socketInitializedRef.current && socketOptions.startClosed !== true) socket.reconnect(); socketInitializedRef.current = socket; return () => { socket.close(); }; } }, [socket, socketOptions, enabled]); return socket; } //#endregion //#region src/use-ws.ts function useWebSocket(url, protocols, options = {}) { const socket = useStableSocket({ options, createSocket: (options$1) => new ReconnectingWebSocket(url, protocols, options$1), createSocketMemoKey: (options$1) => JSON.stringify([ url, protocols, ...getOptionsThatShouldCauseRestartWhenChanged(options$1) ]) }); useAttachWebSocketEventHandlers(socket, options); return socket; } //#endregion export { useAttachWebSocketEventHandlers as i, getOptionsThatShouldCauseRestartWhenChanged as n, useStableSocket as r, useWebSocket as t }; //# sourceMappingURL=use-ws-CTzGXZsh.js.map