React Native Video Calling Tutorial

Let's explore how to create a React Native video calling app, NativeCall, for seamless cross-platform video calls on iOS and Android with a single code base. This app will give you WhatsApp-style audio/video calling experiences with optimal latency, reliability, quality, and customizable permissions

This tutorial teaches you how to build Zoom/Whatsapp style video calling 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.

Preview of the video view

Step 1 - Setup a new React Native app

Create a new React Native app using the official template,

Step 2 - Install the SDK and declare permissions

In order to install the Stream Video React Native SDK, run the following command in your terminal of choice:

The SDK requires installing some peer dependencies. You can run the following command to install them:

Declare permissions

Application needs permissions to access camera, microphone and network state.

  1. Android
  2. iOS

In AndroidManifest.xml add the following permissions before the application section.

If you plan to also support Bluetooth devices then also add the following.

Android Specific installation

In android/build.gradle add the following inside the buildscript section:

In android/app/build.gradle add the following inside the android section:

In android/ add the following:

Run the app

To ensure the best possible experience, we highly recommend running the app on a physical device. This is due to the limitations in audio and video device support on emulators. You can refer to the React Native documentation for guidance on running the app on a physical device.

However, if you still prefer to use an emulator, execute the following command:

Step 3 - Understand the basics

Before we dive deep into writing code, there are two concepts you should be familiar with - StreamVideoClient and Call.

StreamVideoClient is the low level JavaScript client used by the SDK to communicate with the Stream Video service. It provides all the necessary methods to connect user Stream service, query calls, create call etc. And a call refers to an instance of the Call class and is utilized for performing call-specific actions, such as joining a call, muting participants, leaving a call, and more.

In this example

  • apiKey is the API key of your Stream Video application available on dashboard
  • user is the user object { id: "john_smith", "name": "John Smith" }
  • and token is the user token generated by your server-side API. For development purpose, you can use the token generated by the Token Generator. You can read more information about client authentication on the Client & Authentication guide.

Client instance and call instance are made accessible to all the video components from SDK via StreamVideo component and StreamCall component respectively. In your app you need to wrap your component tree with StreamVideo component and provide the client instance to it as a prop. client creation would normally take place during sign-in stage of the application. And similarly you need to wrap your call specific UI components with StreamCall component and provide the call instance to it as a prop.

StreamVideo and StreamCall components are basically context providers, and they enable you to consume hooks provided by the SDK. These hooks do all the heavy lifting around call management and provide you with the necessary state and methods to build your UI.

Step 4 - Setup Starter UI

Lets begin by creating a basic UI for our audio room. Normally you would use a navigation library like React Navigation to navigate between screens. But for this tutorial we'll keep it simple and mock the navigation using a state variable - activeScreen.

Within your tutorial app, create a folder named src and create the following files within it:

  • src/HomeScreen.tsx
  • src/CallScreen.tsx (takes callId as a prop)

Now copy the following content into the respective files (as mentioned in header):

  1. App.tsx
  2. src/CallScreen.tsx
  3. src/HomeScreen.tsx

In App.tsx we have hardcoded the placeholders of apiKey, userId, token and callId for simplicity of tutorial. 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_API_KEY, REPLACE_WITH_USER_ID, REPLACE_WITH_TOKEN and REPLACE_WITH_CALL_ID with the actual values shown below:

In actual application you will want to store apiKey in a secure storage or in environment file.

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 ...

Hit save and you should see on your emulator or device the following UI.

Preview of the Home ScreenPreview of empty video UI
Preview of the Home Screen Preview of empty video UI

Step 5 - Setup Video Client

Within this configuration, we will establish a StreamVideoClient instance and facilitate the user's connection to the Stream Video service. In real application, client creation should be encapsulated within a useEffect hook and during unmount you should call client.disconnectUser() to avoid creating multiple websockets.

Client instance needs to be provided to StreamVideo component and it will provide the client instance to all the child components using React Context. It needs to go at the top of the component tree.

You wouldn't see any change in the UI at this point, since we haven't joined the call yet.

Step 6 - Create & Join a call

In this step we will create and join a call. Call will be stored in a state variable call and it needs to be provided to StreamCall component. As explained earlier, StreamCall component is provided by the SDK and it provides all the necessary hooks for configuring UI around audio room. We will explore these hooks later in the tutorial.

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

Also as explained earlier in Understand the Basics section, call can be created or accessed using method. Thus we need access to client inside CallScreen component. We will use the useStreamVideoContext hook to get access to the client instance.

We will put the joining logic inside useEffect hook, so we automatically join the call when user goes to CallScreen.

To enhance the interactivity of this tutorial moving forward, kindly follow these steps:

  • Give the app a refresh, then tap the "Join Audio Room" button within your mobile tutorial app.
  • Access the web version of the audio room on your browser by clicking the "Join Call" link provided below, and subsequently, hit the "Join" button.

Currently, you won't have the ability to speak, as we haven't set up the user interface for the video call. However, you will be able to view the current user listed among the participants on the web application.

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

Step 7 - Rendering Video UI

In this step, we are going to add the participant's view which displays the participants' video and audio stream and other related info. It will also add buttons that allow the user to control their streaming settings of audio and video.

The CallContent adds the following things to the UI automatically:

  • Indicators of when someone is speaking.
  • Quality of their network.
  • Layout support for multiple participants.
  • Labels for the participant names, media stream on/off status.
  • A floating local video view.
  • Buttons to toggle audio/video and to flip the camera.
  • Button to hang up the call.

Update the CallScreen component as below:

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. You should also see the buttons to control the streaming settings. The end result should look like this:

Preview of the video view

Step 8 - 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 common video UIs).
  • Theming (basic customization of colors, fonts etc).

You can provide custom component as prop to CallContent to customize the UI. Example below shows how you can

Preview of the video view

All essential call information can be accessed through the SDK's provided hooks, facilitated by the StreamCall component. You can conveniently access a range of hooks related to the call's state by utilizing the useCallStateHooks hook as demonstrated below. By utilizing these hooks, you can confidently depend on the most up-to-date state information.

In the following example we will customize the top bar of the CallContent to display

  • current participants in the call
  • name of the dominant speaker

Preview of the video view

You can also adjust the style of the underlying UI using the style prop on StreamVideo component. The complete array of properties that can be themed is available within the theme file.

Preview of the video view


Please do let us know if you ran into any issues while building an video calling app with React Native. 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 about Stream video calling:

  • You set up a call: (const call ="default", "your-call-id"))
  • The call type ("default" in the above case) controls which features are enabled and how permissions are setup
  • When you join a call, real-time communication is set up for audio & video calling: (call.join())
  • State-related hooks such as useCallCallingState make it easy to build your own UI
  • CallContent is the component that renders audio and video and adds buttons to control streaming options

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 Native SDK enables you to build in-app video calling, audio rooms and livestreaming in days.

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 Native messaging app with our React Native SDK component library. We also showed how easy it is to customize the behavior and the style of the React Native video app components with minimal code changes.

Both the video SDK for React Native 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 Native 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