Dynamic room switching

We can add a way for our video-conferencing users to dynamically switch to one of the other currently active room sessions. We are going to add to the room UI a button that shows a list of active room sessions and allows to switch to one of those:

Backend

First, we need to update our server to allow clients to obtain a list of active room sessions. Let's go back to the backend that we built in Writing a backend to proxy SignalWire Video REST API, and let's add the following endpoint:

app.get("/rooms", async (req, res) => {
  const rooms = await axios.get(`${apiurl}/rooms`, { auth })
  res.json(rooms.data.data)
})

When a GET request is made to our /rooms endpoint, we retrieve the list of rooms from SignalWire and we pass the data back to our client. To get the rooms we use the REST API.

Frontend

App.js

In App.js we had defined our InCall UI as a component in the DOM as follows:

<InCall roomDetails={roomDetails} />

This was fine, because changing room was only possible from the outside of the InCall component. Since now we need to change room from within the InCall component, let's add a new event to it.

<InCall
  roomDetails={roomDetails}
  onRoomChange={(room) => {
    setRoomDetails({ name: roomDetails.name, room, mod: roomDetails.mod })
  }}
/>

We still need to update our InCall component to a) display the UI to change rooms, and b) generate onRoomChange events.

InCall.js

In InCall.js, first let's add the onRoomChange parameter to the signature of the component:

export default function InCall({ roomDetails, onRoomChange }) {
  ...
}

Then, we want to keep in the state a list of available rooms. Let's add a new state variable rooms:

export default function InCall({ roomDetails, onRoomChange }) {
  // ...
  const [memberList, setMemberList] = useState([]);  // previous code for context
  const [rooms, setRooms] = useState([]);  // add this line

After that, let's define a function refreshRoomList to update the state with a fresh list of rooms from the server. We also call that function once when our component loads.

  function refreshRoomList() {
    axios.get("/rooms").then(v => {
      setRooms(v.data.map(room => room.name))
    })
  }
  useEffect(refreshRoomList, [])

The last function that we define is an event handler for when our room selector will be clicked by the user. In that case, we need to leave the current room and call the onRoomChange callback defined above.

  function roomSelected(roomName) {
    room.leave()
    onRoomChange(roomName)
  }

After all our functions are defined, we can add our button to the UI:

<DropdownButton
  title="Rooms"
  variant="success"
  drop="up"
  onClick={() => refreshRoomList()}
>
  {rooms.filter(r => r !== roomDetails.room).map(roomName => (
    <Dropdown.Item
      key={roomName}
      onClick={() => roomSelected(roomName)}
    >{roomName}</Dropdown.Item>
  ))}
</DropdownButton>

As a final touch, we want our <Video> component to reload whenever the roomDetails change. We can help React by providing a key like this:

<Video
  key={JSON.stringify(roomDetails)}
  ...
/>

Whenever the room details change, the key will change too and this will trigger a re-render of the <Video> component, which will then re-connect to the correct room.

You can find the complete application on CodeSandbox, and on GitHub in the branch "extras":


Did this page help you?