const socketUrl = "https://webrtc.theuy.nl";
const signalingChannel = createIoSignalingChannel(socketUrl, {
  autoConnect: true
});
root.render(
  <StrictMode>
    <SignalingChannelProvider signalingChannel={signalingChannel}>
      <App />
    </SignalingChannelProvider>
  </StrictMode>
);
import createIoSignalingChannel, {
  SignalingChannelProvider
} from "webrtc-react-socketio/signaling";

Step 1: Create signaling channel

Import our package

Initialize the signaling channel

Provide the signaling channel to our app

export default function App() {
  // use signaling channel
  const { isConnected, join, broadcast } = useSignalingChannel();
  const [room, setRoom] = useState<string>();

  // change the room when we get a room id from the server
  const onResponseCallback: OnResponseCallback = useCallback((response) => {
    setRoom(response.room.id);
  }, []);

  // create room callback
  const createRoom = useCallback((isBroadcast = true) => {
    const payload = { onResponseCallback };
    isBroadcast ? broadcast(payload) : join(payload);
  }, [broadcast, join, onResponseCallback]);

  // show create broadcast button or render our Room
  return !isConnected ? (
    <span>loading...</span>
  ) : !room ? (
    <button onClick={() => createRoom()}>Create Broadcast</button>
  ) : (
    <AudioRoom room={room} />
  );
}

Step 2: Handle room creation

Now we can use our signaling channel in our react components

const [isRecording, setIsRecording] = useState(false);
const audioRef = useRef<HTMLAudioElement>(null);
const streamRef = useRef<MediaStream>();

Step 3: Create our room component

Add some state and refs to facilitate the audio tracks

const { addTrack, removeTrack } = usePeerConnection({
  room,
  onTrack: (track) => {
    if (audioRef.current) {
      audioRef.current.srcObject = track.streams[0];
    }
    track.streams[0].onremovetrack = () => {
      if (audioRef.current) {
        audioRef.current.srcObject = null;
      }
    };
  }
});

Initialize peer connection and listen for audio tracks

const toggleBroadcast = useCallback(async () => {
  if (!streamRef.current) {
    const stream = await navigator.mediaDevices.getUserMedia({
      audio: true,
      video: false
    });
    stream.getTracks().forEach((track) => addTrack(track, stream));
    streamRef.current = stream;
    setIsRecording(true);
  } else {
    streamRef.current.getTracks().forEach((track) => track.stop());
    streamRef.current = undefined;
    removeTrack();
    setIsRecording(false);
  }
}, [addTrack, removeTrack]);

Step 3: Create our room component

Toggle broadcast callback

return (<div>
  <audio ref={audioRef} autoPlay />
  <button onClick={() => toggleBroadcast()}>
    {isRecording ? "Stop" : "Start"} recording
  </button>
</div>);

Render audio element and recording toggle button

import { useCallback, useEffect } from "react";
import { usePeerConnection } from "webrtc-react-socketio";
import { useSignalingChannel } from "webrtc-react-socketio/signaling";

export default function TextRoom({ room }: { room: string }) {
  const { socket } = useSignalingChannel();
  const { createDataChannel, sendMessage } = usePeerConnection({
    room,
    onMessage: (data) => console.log("new message", data)
  });

  const onNewMember = useCallback(
    ({ room, from: remotePeerId }: { room: string; from: string }) => {
      createDataChannel({ room, remotePeerId });
    },
    [createDataChannel]
  );

  useEffect(() => {
    socket.on("new member", onNewMember);
    return () => {
      socket.off("new member", onNewMember);
    };
  }, [socket, onNewMember]);

  return <button onClick={() => sendMessage({ message: "randomstring" })}>
    Send
  </button>;
}

BONUS: Room example with data channels

Made with Slides.com