Building a YouTube Component Using the React-Native WebView | by Daniel Friyia | Mar, 2022

Add YouTube Player functionality to your React-Native App

Recently, I was working on an app that required access to YouTube videos. To my surprise, there wasn’t much in the way of good libraries on NPM. After taking a deep dive on YouTube and React-Native development, I realized that YouTube wants you to just use their embed.

This posed an interesting problem.

If we were working in browser-based JavaScript, it would be trivial to just copy and paste the JS from the YouTube documentation. When working on mobile though, we don’t have the same luxury. Luckily, the WebView in React-Native provides a robust API that allows us to communicate between mobile and the WebView’s browser.

In this blog, I’ll be explaining how we can take advantage of that API to create a YouTube component we can control from React-Native. As always, if you get stuck at any point, check out the complete project repo here.

Today, we’ll be building this simple app that plays videos through the YouTube embed. You’ll learn how to display videos as well as how to communicate between the WebView’s JavaScript and React-Native.

The first thing you’ll want to do is generate an empty TypeScript project using this command:

npx react-native init YoutubePlayer --template react-native-template-typescript

After generating the project, run the following command to install the react-native-webview:

npm i react-native-webview

Finish up by installing the new Cocoapods in your project.

cd ios && npx pod install

When using a complex web component like the YouTube player, we can’t just pop in a URL and watch the WebView work. In order to support such a feature-rich component, we need to use the YouTube embed.

I recommend starting by creating a file called iFrame.tsx under your src directory. After creating this file, we can start by making a function called buildIFrame. This function will build the embed part of our HTML code.

Start by adding a player div that we can use as a target for the embed.

const buildIFrame = (videoId: string) => `
<div id="player"></div>

Next, we’ll want to build the script that makes the YouTube player appear. We start by loading the iFrame player code asynchronously.

...
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
...

At this point, we need to create the YouTube player and target the player div we created. We do this as follows:

The videoId will be passed in a bit later, but for now, you can get the screen width from the React Native dimensions like this.

import {Dimensions} from 'react-native';
const {width} = Dimensions.get('window');

Your buildIFrame function so far should be as follows.

The next step is to style our iFrame. Keep in mind the styles for this are pretty specific. This is because we want the iFrame to fill its parent view.

Finally, let’s create a method that takes in a videoId from YouTube and uses it to build the entire iFrame HTML page.

Now that we have the markup we need, let’s create the WebView Component. Navigate back to your App.tsx file. At this point, you want to import the WebView component and use it along with the buildHTML function we just finished creating. Altogether, the file should look like this:

At this point, you should be able to watch the video if you tap on it.

To create the controls we are going to add more code to the buildIFrame function from earlier. On the web, the YouTube player gives you access to several functionalities. The ones we use in this project are playing and pausing the video, seeking a time, and getting the current time in the video.

We wrap these functionalities in JavaScript browser functions so we can call them from React-Native later on. After doing this, your buildIFrame will take this form.

Back in the App.tsx file, we have the trivial task of wrapping these functions in React-Native functions so that we can call them in the browser. Start by grabbing a ref to the WebView.

const webRef = useRef<WebView>(null);
...
<WebView
ref={webRef}

After that, you can call whatever JavaScript functions you want on the WebView. Here are the ones we’ll use for this project:

const playVideo = () => {
webRef.current?.injectJavaScript('play()');
};
const pauseVideo = () => {
webRef.current?.injectJavaScript('pause()');
};
const restartVideo = () => {
webRef.current?.injectJavaScript('seekTo(0)');
};

If we throw in a few buttons and some light styling, our component ends up in its penultimate form.

We’re almost there! At this point, you should be able to play the video with the controls.

The last thing we’ll want to do is display the timer. To do this, we’ll have to post messages from the WebView and send them to React-Native every second or so.

We can add this functionality to our WebView using the postMessage function. You can add this snippet to your iFrame.ts.

setInterval(() => {
const data = {
currentDuration: getCurrentTime()
}
window.ReactNativeWebView.postMessage(JSON.stringify(data));
}, 1000)

The function should now contain the set interval, shown below:

We can finish up by grabbing these events from the WebView and displaying them using a state. Your final App.tsx will look like this:

Your final result should be this:

Video playing with a play, pause, restart, and timer under it.

With YouTube being the primary hosting service on the internet, it’s really important to be able to use it in our apps. Above, I gave you the basics for how to add it to your app.

Feel free to style the controls as you see fit in order to suit your user experience!

Leave a Comment