diff --git a/src/contexts/room-context.tsx b/src/contexts/room-context.tsx index 4dbc3c4..aa539ad 100644 --- a/src/contexts/room-context.tsx +++ b/src/contexts/room-context.tsx @@ -241,19 +241,19 @@ export function RoomProvider({ if (!activeRoomId || !client) return; const setup = async () => { - if (client.getStatus() !== 'open') { - await client.connect(); - } - // Re-check: activeRoomId may have changed while we were waiting for connect. - // Use activeRoomIdRef to get the *current* room, not the stale closure value. - const roomId = activeRoomIdRef.current; - if (!roomId) return; - await client.subscribeRoom(roomId); - // loadMoreRef.current is null on first mount (set later in render order). - // Call loadMore directly to ensure initial message fetch always runs. + // Ensure WS is open before subscribing. connect() is idempotent — if already + // connecting/open, it returns immediately. While connecting, messages load from + // IDB (instant) and reactions batch-fetch via WS-first request(). + await client.connect(); + // Guard: room may have changed while we were waiting for connect. + if (activeRoomIdRef.current !== activeRoomId) return; + // subscribeRoom is WS-first with HTTP fallback; failure is non-fatal. + client.subscribeRoom(activeRoomId).catch(() => {}); + // loadMore checks IDB first (no WS needed), then batch-fetches reactions + // via WS with HTTP fallback. Safe to call without awaiting. loadMore(null); }; - setup(); + setup().catch(() => {}); return () => { client.unsubscribeRoom(activeRoomId).catch(() => {});