Code areas for setting up client connections to the server are contained in the @connection/
folder.
They are provided with basic room settings by the Room page, set up React Contexts that provide rudimentary connection APIs, then render the Room page as children underneath those contexts.
Initializing the context consists of three phases, each corresponding to a React component that renders the next step when ready:
DynamicScene
DynamicSceneHydrating
DynamicSceneConnected
DynamicScene
receives basic settings directly passed by the page query and calls useRoomConnection
to:
- Initialze the NAF connection by setting the
networked-scene
attribute on the root Aframe scene, providing aglobalOnConnectHook
to NAF'sonConnect
pointing to our temporarily created global listener. - Upon connection success in that global listener, stores NAF's Socket.IO client in our React state.
That stored socket client is used by the rest of the connection logic to send data to and receive data from the server.
DynamicSceneHydrating
takes in that socket and calls useRoomDataConnection
to:
- Send a
KaraokeEvent.RoomDataHydration
event to the server requesting a summary of room information. - Upon receiving the response, store the room information in React state.
That stored room data is used by the rest of the connection and room logic to keep a local copy of the most recent snapshot of the room's state.
DynamicSceneConnected
receives accumulated client and room data state, and uses them to initialize contexts used by the rest room logic:
EmitContext
receives a singleemit
function clients may send events to the server through.RoomContext
receives [GetterAndSetter
] wrappers around room data, as well as an [emitRoomData
] utility to simultaneously update local room data and send any changed values to the server.
It also starts a useRoomDataSyncing
effect that continuously synchronizes local state to the server as it changes:
- It immediately emits a
KaraokeEvent.UsernameSet
to indicate the user's selected username to the server. - When a
KaraokeEvent.OccupantsUpdated
event is received, it updates the local occupancy map. - When a
KaraokeEvent.RoomDataUpdated
event is received, it updates the local room data.
Use useRoomContext()
to take a dependency on part of the room context in a component.
The .get()
method on values provided by the room context each return readonly versions of the state.
const { roomName } = useRoomContext();
roomName.get(); // string
The commonly used roomData
member is a full object, so it's convenient to destructure its .get()
immediately:
const { roomData } = useRoomContext();
const { currentTime } = roomData.get();
currentTime; // string
The .set()
method on those members takes in a new version to pass to a setState
setter.
const { occupants } = useRoomContext();
occupants.set(newOccupancyMap);
For RoomData
specifically, use the returned emitRoomData
function to simultaneously update local room data and send any changed values to the server.
const { emitRoomData, roomData } = useRoomContext();
emitRoomData({
songs: [...roomData.get().songs, newSong],
});