Files
skills/docs/ui/react/react-audio-stream/src/hooks/use-stream-room/use-stream-room.md
2026-05-29 08:20:56 +01:00

1.9 KiB

use-stream-room

(no submodules)

Purpose

useStreamRoom projects the current room scope out of the session: the room id (or null when the session is not connected), an isJoined boolean derived from the FSM state, the joinedAt epoch-milliseconds timestamp, and the live participant list (remote peers only — the local user is represented via the session itself, not the participant array).

The hook is intentionally cheap and read-only; components that render the room header, the participant chip-list, or any "you have not joined yet" empty state can depend on it without pulling in the heavier mixer/level/recording surfaces.

Features

  • Pure projection — no callbacks, no side effects.
  • participants is a stable reference between renders when peers have not changed, thanks to the memoisation barrier and the session's own array stability contract.
  • Throws REACT_AUDIO_STREAM.NO_PROVIDER when used without a <StreamProvider>.

Usage: Basic

const { roomId, isJoined, participants } = useStreamRoom();
if (!isJoined) return <JoinButton />;
return (
    <header>
        <h2>{roomId}</h2>
        <p>{participants.length} present</p>
    </header>
);

Usage: Advanced

const { participants, joinedAt } = useStreamRoom();
const elapsedMs = joinedAt === null ? 0 : Date.now() - joinedAt;
return (
    <Stats elapsedMs={elapsedMs} peerIds={participants.map((p) => p.id)} />
);

API Reference

  • UseStreamRoomResult — { roomId, isJoined, joinedAt, participants }
  • useStreamRoom(): UseStreamRoomResult

Implementation Notes

isJoined is derived from session.state === "joined" rather than from a separate isJoined field on the session, because the FSM state is the single source of truth (see Requirement "StreamSession FSM lifecycle"). The participant array is read via session.getPeers() on every render; the provider's render-bump version keeps that read fresh.