From ce3904f558b41866fdfce9318abab304fedf1a06 Mon Sep 17 00:00:00 2001 From: zxcodes Date: Mon, 19 May 2025 12:05:06 +0530 Subject: [PATCH 1/2] add enabled prop. --- packages/partysocket/src/use-ws.ts | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/packages/partysocket/src/use-ws.ts b/packages/partysocket/src/use-ws.ts index d7fa27fe..be558ff9 100644 --- a/packages/partysocket/src/use-ws.ts +++ b/packages/partysocket/src/use-ws.ts @@ -8,7 +8,13 @@ import WebSocket from "./ws"; import type { EventHandlerOptions } from "./use-handlers"; import type { Options, ProtocolsProvider, UrlProvider } from "./ws"; -type UseWebSocketOptions = Options & EventHandlerOptions; +type UseWebSocketOptions = Options & + EventHandlerOptions & { + /** + * Whether to enable WebSocket connection (if `false`, connection won't be established. Defaults to `true`) + */ + enabled?: boolean; + }; // A React hook that wraps PartySocket export default function useWebSocket( @@ -16,9 +22,17 @@ export default function useWebSocket( protocols?: ProtocolsProvider, options: UseWebSocketOptions = {} ) { + const { enabled = true, ...restOptions } = options; + const socket = useStableSocket({ - options, - createSocket: (options) => new WebSocket(url, protocols, options), + options: restOptions, + createSocket: (options) => { + if (!enabled) { + return null; + } + + return new WebSocket(url, protocols, options); + }, createSocketMemoKey: (options) => JSON.stringify([ // will reconnect if url or protocols are specified as a string. @@ -29,7 +43,7 @@ export default function useWebSocket( ]) }); - useAttachWebSocketEventHandlers(socket, options); + useAttachWebSocketEventHandlers(socket!, restOptions); return socket; } From 6de5ca0591020d1d244eaa6f1c30dd67a9df26e1 Mon Sep 17 00:00:00 2001 From: zxcodes Date: Mon, 19 May 2025 12:05:33 +0530 Subject: [PATCH 2/2] update types handle null values. --- packages/partysocket/src/react.ts | 2 +- packages/partysocket/src/use-handlers.ts | 18 +++++++++--------- packages/partysocket/src/use-socket.ts | 8 ++++---- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/partysocket/src/react.ts b/packages/partysocket/src/react.ts index 0646814e..1f1fd794 100644 --- a/packages/partysocket/src/react.ts +++ b/packages/partysocket/src/react.ts @@ -45,7 +45,7 @@ export default function usePartySocket(options: UsePartySocketOptions) { ]) }); - useAttachWebSocketEventHandlers(socket, options); + useAttachWebSocketEventHandlers(socket!, options); return socket; } diff --git a/packages/partysocket/src/use-handlers.ts b/packages/partysocket/src/use-handlers.ts index b7d91022..1e97bb2c 100644 --- a/packages/partysocket/src/use-handlers.ts +++ b/packages/partysocket/src/use-handlers.ts @@ -11,7 +11,7 @@ export type EventHandlerOptions = { /** Attaches event handlers to a WebSocket in a React Lifecycle-friendly way */ export const useAttachWebSocketEventHandlers = ( - socket: WebSocket, + socket: WebSocket | null, options: EventHandlerOptions ) => { const handlersRef = useRef(options); @@ -27,16 +27,16 @@ export const useAttachWebSocketEventHandlers = ( const onError: EventHandlerOptions["onError"] = (event) => handlersRef.current?.onError?.(event); - socket.addEventListener("open", onOpen); - socket.addEventListener("close", onClose); - socket.addEventListener("error", onError); - socket.addEventListener("message", onMessage); + 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?.removeEventListener("open", onOpen); + socket?.removeEventListener("close", onClose); + socket?.removeEventListener("error", onError); + socket?.removeEventListener("message", onMessage); }; }, [socket]); }; diff --git a/packages/partysocket/src/use-socket.ts b/packages/partysocket/src/use-socket.ts index fb0753de..64c8fde9 100644 --- a/packages/partysocket/src/use-socket.ts +++ b/packages/partysocket/src/use-socket.ts @@ -28,7 +28,7 @@ export function useStableSocket({ createSocketMemoKey: createOptionsMemoKey }: { options: TOpts; - createSocket: (options: TOpts) => T; + createSocket: (options: TOpts) => T | null; createSocketMemoKey: (options: TOpts) => string; }) { // ensure we only reconnect when necessary @@ -39,7 +39,7 @@ export function useStableSocket({ }, [shouldReconnect]); // this is the socket we return - const [socket, setSocket] = useState(() => + const [socket, setSocket] = useState(() => // only connect on first mount createSocket({ ...socketOptions, startClosed: true }) ); @@ -68,13 +68,13 @@ export function useStableSocket({ } else { // if this is the first time we are running the hook, connect... if (!socketInitializedRef.current && socketOptions.startClosed !== true) { - socket.reconnect(); + socket?.reconnect(); } // track initialized socket so we know not to do it again socketInitializedRef.current = socket; // close the old socket the next time the socket changes or we unmount return () => { - socket.close(); + socket?.close(); }; } }, [socket, socketOptions]);