Skip to main content
Version: Next

React/Web Quick Start

This tutorial will guide you through integrating Fishjam into your React web application step by step.
By the end, you'll have a working video streaming web app and understand the core concepts.

What you'll build

A simple React web app that can join video calls and stream video between participants.

What you'll learn

  • How to install and set up Fishjam for React
  • How to join a room and start streaming
  • How to display video from other participants
  • How to manage media devices

Prerequisites

Step 1: Install and set up

Install the package

npm install @fishjam-cloud/react-client

Get your Fishjam ID and Sandbox API URL

  1. Log in to Fishjam Dashboard
  2. Navigate to the Sandbox tab
  3. Copy your Fishjam ID
  4. Copy your Sandbox API URL from the Sandbox API section

The Fishjam ID is required by FishjamProvider to connect to the media server. The Sandbox API URL is used by useSandbox to request test peer tokens.

Set up Fishjam context

Wrap your app in the FishjamProvider component:

// Check https://fishjam.io/app/ for your Fishjam ID const FISHJAM_ID = "YOUR_FISHJAM_ID"; ReactDOM.createRoot(document.getElementById("root")!).render( <React.StrictMode> <FishjamProvider fishjamId={FISHJAM_ID}> <App /> </FishjamProvider> </React.StrictMode>, );

Step 2: Join a room and start streaming

Create a component that joins a room and starts streaming:

import React from "react"; import { useConnection, useCamera, useInitializeDevices, useSandbox, } from "@fishjam-cloud/react-client"; const SANDBOX_API_URL = "YOUR_SANDBOX_API_URL"; export function JoinRoomButton() { const { joinRoom } = useConnection(); const { selectCamera } = useCamera(); const { initializeDevices } = useInitializeDevices(); const { getSandboxPeerToken } = useSandbox({ sandboxApiUrl: SANDBOX_API_URL, }); const handleJoinRoom = async () => { const roomName = "testRoom"; const peerName = "testUser"; // For testing with the Sandbox API, use getSandboxPeerToken // For production apps, get the peerToken from your own backend instead const peerToken = await getSandboxPeerToken(roomName, peerName); // Start camera by selecting the first available camera await initializeDevices({ enableAudio: false }); // or just initializeDevices(); if you want both camera and mic // Join the room await joinRoom({ peerToken }); }; return <button onClick={handleJoinRoom}>Join Room</button>; }

Step 3: Display other participants

Show video from other peers:

import React from "react"; import { useEffect, useRef } from "react"; import { usePeers } from "@fishjam-cloud/react-client"; function VideoPlayer({ stream }: { stream: MediaStream | null | undefined }) { const videoRef = useRef<HTMLVideoElement>(null); useEffect(() => { if (!videoRef.current) return; videoRef.current.srcObject = stream ?? null; }, [stream]); return <video ref={videoRef} autoPlay playsInline />; } export function ParticipantsView() { const { remotePeers } = usePeers(); return ( <div> {remotePeers.map((peer) => ( <div key={peer.id}> {peer.cameraTrack?.stream && ( <VideoPlayer stream={peer.cameraTrack.stream} /> )} </div> ))} </div> ); }

Step 4: Display your video

Show your own video stream:

import React from "react"; import { useCamera } from "@fishjam-cloud/react-client"; export function MyVideo() { const { cameraStream } = useCamera(); return <VideoPlayer stream={cameraStream} />; }

Step 5: Handle connection status

Monitor your connection:

import React from "react"; import { useConnection } from "@fishjam-cloud/react-client"; export function ConnectionStatus() { const { peerStatus } = useConnection(); return <div>Status: {peerStatus}</div>; }

Complete example

Here's a complete working app:

function VideoPlayer({ stream }: { stream: MediaStream | null | undefined }) { const videoRef = useRef<HTMLVideoElement>(null); useEffect(() => { if (!videoRef.current) return; videoRef.current.srcObject = stream ?? null; }, [stream]); return <video ref={videoRef} autoPlay playsInline />; } function VideoCall() { const { joinRoom, peerStatus } = useConnection(); const { cameraStream } = useCamera(); const { remotePeers } = usePeers(); const { initializeDevices } = useInitializeDevices(); const { getSandboxPeerToken } = useSandbox({ sandboxApiUrl: SANDBOX_API_URL, }); const [isJoined, setIsJoined] = useState(false); const handleJoin = async () => { const roomName = "testRoom"; const peerName = `user_${Date.now()}`; // Initialize devices first await initializeDevices(); // For testing with the Sandbox API, use getSandboxPeerToken // For production apps, get the peerToken from your own backend instead const peerToken = await getSandboxPeerToken(roomName, peerName); await joinRoom({ peerToken }); setIsJoined(true); }; return ( <div> <h1>Fishjam Video Call</h1> <p>Status: {peerStatus}</p> {!isJoined && <button onClick={handleJoin}>Join Room</button>} {cameraStream && ( <div> <h3>Your Video</h3> <VideoPlayer stream={cameraStream} /> </div> )} <div> <h3>Other Participants</h3> {remotePeers.map((peer) => ( <div key={peer.id}> {peer.cameraTrack?.stream && ( <VideoPlayer stream={peer.cameraTrack.stream} /> )} </div> ))} </div> </div> ); } export default function App() { return ( <FishjamProvider fishjamId={FISHJAM_ID}> <VideoCall /> </FishjamProvider> ); }

Next steps

Now that you have a basic app working, explore these how-to guides:

Or learn more about Fishjam concepts: