Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/partysocket/src/react.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export default function usePartySocket(options: UsePartySocketOptions) {
])
});

useAttachWebSocketEventHandlers(socket, options);
useAttachWebSocketEventHandlers(socket!, options);

return socket;
}
Expand Down
18 changes: 9 additions & 9 deletions packages/partysocket/src/use-handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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]);
};
8 changes: 4 additions & 4 deletions packages/partysocket/src/use-socket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export function useStableSocket<T extends WebSocket, TOpts extends Options>({
createSocketMemoKey: createOptionsMemoKey
}: {
options: TOpts;
createSocket: (options: TOpts) => T;
createSocket: (options: TOpts) => T | null;
createSocketMemoKey: (options: TOpts) => string;
}) {
// ensure we only reconnect when necessary
Expand All @@ -39,7 +39,7 @@ export function useStableSocket<T extends WebSocket, TOpts extends Options>({
}, [shouldReconnect]);

// this is the socket we return
const [socket, setSocket] = useState<T>(() =>
const [socket, setSocket] = useState<T | null>(() =>
// only connect on first mount
createSocket({ ...socketOptions, startClosed: true })
);
Expand Down Expand Up @@ -68,13 +68,13 @@ export function useStableSocket<T extends WebSocket, TOpts extends Options>({
} 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]);
Expand Down
22 changes: 18 additions & 4 deletions packages/partysocket/src/use-ws.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,31 @@ 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(
url: UrlProvider,
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.
Expand All @@ -29,7 +43,7 @@ export default function useWebSocket(
])
});

useAttachWebSocketEventHandlers(socket, options);
useAttachWebSocketEventHandlers(socket!, restOptions);

return socket;
}
Loading