React Video Calling Tutorial

Learn how to build a video calling application in React using the Stream Video and Audio SDK. Follow our Developer Advocate, Stefan, on the journey of building up a project from scratch and going to a fully functional calling app that you can directly test from within the browser. No pre-requisites, pure fun.

This tutorial teaches you how to build Zoom/Whatsapp style video calling experience for your app.

  • Calls run on Stream's global edge network for optimal latency & reliability.
  • Permissions give you fine grained control over who can do what.
  • Video quality and codecs are automatically optimized.
  • Powered by Stream's Video Calling API.

Step 0 - Prepare your environment

For this tutorial, you'll need a few tools to be installed on your device. You can skip this step in case you already have them installed.

  • Node.js (version 18 or higher)
  • Yarn (version 1.22 or higher)

Step 1 - Set up an app and install React Video SDK

In this step, we will create a new React application using the Vite CLI, and install Stream's React Video SDK. We recommend using Vite because it is fast and easy to use.

Step 2 - Create & Join a call

Open up src/App.tsx and replace it with this code:

To actually run this sample we need a valid user token. The user token is typically generated by your server side API. When a user logs in to your app you return the user token that gives them access to the call. To make this tutorial easier to follow we'll generate a user token for you:

Please update REPLACE_WITH_USER_ID, REPLACE_WITH_TOKEN and REPLACE_WITH_CALL_ID with the actual values shown below:

Here are credentials to try out the app with:

API KeyWaiting for an API key ...
Token Token is generated ...
User IDLoading ...
Call IDCreating random call ID ...
For testing you can join the call on our web-app: Join Call

Now when you run the sample app it will connect successfully. The text will say "Call ... has 1 participant" (yourself).

Preview of the step

Let's review what we did in the above code

User setup

First we create a user object. You typically sync these users via a server side integration from your own backend. Alternatively, you can also use guest or anonymous users.

Client setup

Next we initialize the client by passing the API Key, user and user token.

Create and join call

After the user and client are created, we create a call like this:

As soon as you use call.join() the connection for video & audio is setup.

In production grade apps, you'd typically store the call instance in a state variable and take care of correctly disposing it. Read more in our Joining and Creating Calls guide.

Rendering the UI

Lastly, the UI is rendered by observing the call state through the call state hooks (participants and call state):

You'll find all relevant state for the call in call.state also exposed through a set of SDK provided hooks. The documentation on Call and Participant state explains this in further detail.

Step 3 - Joining from the web

To make this a little more interactive, let's join the call from your browser.

For testing you can join the call on our web-app: Join Call

In your browser, you'll see the text update to 2 participants. Let's keep the browser tab open as you go through the tutorial.

Step 4 - Rendering Video

In this next step we're going to render your local & remote participants video.

Let's update our UILayout component to load the predefined SDK stylesheet, apply the default theme and render the video.

We will now create a MyParticipantList component that will render the remote participants video.

Now when you run the app, you'll see your local video in a floating video element and the video from your other browser tab. The end result should look somewhat like this:

Preview of a call running with the local video floating at the top left.

Let's review the changes we made

ParticipantView is one of our primary low-level components.

It only displays the video comes with some default UI elements, such as participant's name. The video is lazily loaded, and only requested from the video infrastructure if you're actually displaying it. So if you have a video call with 200 participants, and you show only 10 of them, you'll only receive video for 10 participants. This is how software like Zoom and Google Meet make large calls work.

MyFloatingLocalParticipant renders a display of your own video.

MyParticipantList renders a list of remote participants.

Step 5 - A Full Video Calling UI

The above example showed how to use the call state and React to build a basic video UI. For a production version app, you'd want a few more UI elements:

  • Indicators of when someone is speaking
  • Quality of their network connection
  • Layout support for more than two participants
  • Labels for the participant names
  • Call controls

Stream React Video SDK ships with several React components to make this easy. You can customize the components with theming, arguments and swapping parts of them. This is convenient if you want to quickly build a production ready calling experience for you app. (and if you need more flexibility, many customers use the above low level approach to build a UI from scratch).

To render a full calling UI, we'll leverage the SpeakerLayout component for arranging the video elements, and the CallControls component for rendering the call controls. Also, we are going to introduce a minimalistic CSS file to make the UI look a bit nicer.

The final UI should look like this:

Final result

When you now run your app, you'll see a more polished video UI. It supports reactions, screensharing, active speaker detection, network quality indicators etc. The most commonly used UI components are:

  • ParticipantView: For rendering video and automatically requesting video tracks when needed. Most of the Video components are built on top of this.
  • DefaultParticipantViewUI: The participant's video + some UI elements for network quality, reactions, speaking etc. ParticipantView uses this UI by default.
  • PaginatedGridLayout: A grid of participants. Support pagination out of the box.
  • SpeakerLayout: A layout that shows the active speaker in a large video, and the rest of the participants a scrollable bar.
  • CallControls: A set of buttons for controlling your call, such as changing audio and video mute state, switching mic or a camera.

The full list of UI components is available in the docs.

Because of simplicity, in this tutorial, we are skipping some of the best practices for building a production ready app. Take a look at our sample app linked at the end of this tutorial for a more complete example.

Step 6 - Customizing the UI

You can customize the UI by:

  • Building your own UI components (the most flexibility, build anything).
  • Mixing and matching with Stream's UI Components (speeds up how quickly you can build custom video UIs).
  • Theming (basic customization of colors, fonts etc).

You can find many examples on how to build your own custom UI components in our UI Cookbook docs.


Please do let us know if you ran into any issues while building an video calling app with React Video SDK. Our team is also happy to review your UI designs and offer recommendations on how to achieve it with Stream.

To recap what we've learned:

  • You setup a call: const call ='default', '123');.
  • The call type ('default' in the above case) controls which features are enabled and how permissions are setup.
  • When you join a call, realtime communication is setup for audio & video calling: call.join().
  • Call state call.state and helper state access hooks exposed through useCallStateHooks() make it easy to build your own UI
  • ParticipantView is the low level component that renders video, plays audio and by default, it utilizes DefaultParticipantViewUI that adds UI elements as participant name, network quality, etc...

We've used Stream's Video Calling API, which means calls run on a global edge network of video servers. By being closer to your users the latency and reliability of calls are better. The React SDK enables you to build in-app video calling, audio rooms and livestreaming in days.

The source code for the final app can be found in our GitHub repository.

We hope you've enjoyed this tutorial and please do feel free to reach out if you have any suggestions or questions.

Final Thoughts

In this video app tutorial we built a fully functioning React messaging app with our React SDK component library. We also showed how easy it is to customize the behavior and the style of the React video app components with minimal code changes.

Both the video SDK for React and the API have plenty more features available to support more advanced use-cases.

Give us Feedback!

Did you find this tutorial helpful in getting you up and running with React for adding video to your project? Either good or bad, we’re looking for your honest feedback so we can improve.

Next Steps

Create your free Stream account to start building with our Video & Audio SDKs at no charge during the open beta. Contact our Product team for free onboarding support or to share any feedback.

Chat Messaging

Build any kind of chat messaging experience without scalability or reliability issues.

Learn more about $ Chat Messaging


Available 99.999% uptime SLAs and industry-leading security to power the world's largest apps.

Learn more about $ Enterprise