UNPKG

partysocket

Version:
150 lines (148 loc) 4.8 kB
import ReconnectingWebSocket from "./ws.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); const optionsChangedWhileDisabledRef = useRef(false); useEffect(() => { const optionsChanged = prevSocketOptionsRef.current !== socketOptions; prevSocketOptionsRef.current = socketOptions; if (!enabled) { socket.close(); prevEnabledRef.current = enabled; if (optionsChanged) optionsChangedWhileDisabledRef.current = true; return () => { socket.close(); }; } if (!prevEnabledRef.current && enabled) { prevEnabledRef.current = enabled; const needsNewSocket = optionsChanged || optionsChangedWhileDisabledRef.current; optionsChangedWhileDisabledRef.current = false; if (!needsNewSocket) { socket.reconnect(); return () => { socket.close(); }; } const newSocket = createSocketRef.current({ ...socketOptions, startClosed: true }); setSocket(newSocket); return () => { newSocket.close(); }; } prevEnabledRef.current = enabled; if (socketInitializedRef.current === socket) if (optionsChanged) { const newSocket = createSocketRef.current({ ...socketOptions, startClosed: true }); setSocket(newSocket); return () => { newSocket.close(); }; } else { if (socketOptions.startClosed !== true) socket.reconnect(); return () => { socket.close(); }; } else { if (!socketInitializedRef.current) { if (socketOptions.startClosed !== true) socket.reconnect(); } else if (socketInitializedRef.current !== socket) 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) => new ReconnectingWebSocket(url, protocols, options), createSocketMemoKey: (options) => JSON.stringify([ url, protocols, ...getOptionsThatShouldCauseRestartWhenChanged(options) ]) }); useAttachWebSocketEventHandlers(socket, options); return socket; } //#endregion export { useAttachWebSocketEventHandlers as i, getOptionsThatShouldCauseRestartWhenChanged as n, useStableSocket as r, useWebSocket as t }; //# sourceMappingURL=use-ws-dP3zNXFn.js.map