Tutorial: React/Web Quick Start
Tutorial - Learn the basics by building your first Fishjam web app
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
- React development environment set up
- Access to Fishjam Dashboard
Step 1: Install and set up
Install the package
- npm
- Yarn
- pnpm
- Bun
npm install @fishjam-cloud/react-client
yarn add @fishjam-cloud/react-client
pnpm add @fishjam-cloud/react-client
bun add @fishjam-cloud/react-client
Set up Fishjam context
Wrap your app in the FishjamProvider
component:
ReactDOM .createRoot (document .getElementById ("root")!).render ( <React .StrictMode > <FishjamProvider > <App /> </FishjamProvider > </React .StrictMode >, );
Get your Room Manager URL
- Log in to Fishjam Dashboard
- Navigate to your Sandbox environment
- Copy your Room Manager URL - you'll need this for testing
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 , } from "@fishjam-cloud/react-client"; // Check https://fishjam.io/app/ for your Room Manager ID constROOM_MANAGER_ID = "YOUR_ROOM_MANAGER_ID"; export functionJoinRoomButton () { const {joinRoom } =useConnection (); const {selectCamera } =useCamera (); const {initializeDevices } =useInitializeDevices (); consthandleJoinRoom = async () => { constroomName = "testRoom"; constpeerName = "testUser"; // Fetch peer token from Room Manager constresponse = awaitfetch ( `https://fishjam.io/api/v1/connect/${ROOM_MANAGER_ID }/room-manager/?roomName=${roomName }&peerName=${peerName }`, ); const {url ,peerToken } = awaitresponse .json (); // Start camera by selecting the first available camera awaitinitializeDevices ({enableAudio : false }); // or just initializeDevices(); if you want both camera and mic // Join the room awaitjoinRoom ({url ,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"; functionVideoPlayer ({stream }: {stream :MediaStream | null | undefined }) { constvideoRef =useRef <HTMLVideoElement >(null);useEffect (() => { if (!videoRef .current ) return;videoRef .current .srcObject =stream ?? null; }, [stream ]); return <video ref ={videoRef }autoPlay playsInline />; } export functionParticipantsView () { 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 functionMyVideo () { 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 functionConnectionStatus () { const {peerStatus } =useConnection (); return <div >Status: {peerStatus }</div >; }
Complete example
Here's a complete working app:
function
VideoPlayer ({stream }: {stream :MediaStream | null | undefined }) { constvideoRef =useRef <HTMLVideoElement >(null);useEffect (() => { if (!videoRef .current ) return;videoRef .current .srcObject =stream ?? null; }, [stream ]); return <video ref ={videoRef }autoPlay playsInline />; } functionVideoCall () { const {joinRoom ,peerStatus } =useConnection (); const {cameraStream } =useCamera (); const {remotePeers } =usePeers (); const {initializeDevices } =useInitializeDevices (); const [isJoined ,setIsJoined ] =useState (false); consthandleJoin = async () => { constroomName = "testRoom"; constpeerName = `user_${Date .now ()}`; // Initialize devices first awaitinitializeDevices (); constresponse = awaitfetch ( `https://fishjam.io/api/v1/connect/${ROOM_MANAGER_ID }/room-manager/?roomName=${roomName }&peerName=${peerName }`, ); const {url ,peerToken } = awaitresponse .json (); awaitjoinRoom ({url ,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 functionApp () { return ( <FishjamProvider > <VideoCall /> </FishjamProvider > ); }
Next steps
Now that you have a basic app working, explore these how-to guides:
- How to manage media devices
- How to implement livestreaming
- How to work with stream middleware
- How to handle custom sources
Or learn more about Fishjam concepts: