Search
  • Sotiris Karapostolou

Embedding youtube videos in a react native app with WebView, Modal && react-navigation

Recently I had to embed a youtube video in a react native app for the project I am working on. Ideally you would use this package react-native-youtube but unfortunately it doesn't support Expo workflow, so at that moment I realized I had to improvise (my favorite moment as a web-developer).



Setting up the Webview

Add this package -- react-native-webview to your project

Now let's create the VideoModal component.


#VideoModal.js

import { Modal } from 'react-native'; 
import WebView from 'react-native-webview';

const _VALIDURL = /^(https?\:\/\/)?((www\.)?youtube\.com|youtu\.?be)\/.+$/;
const _FINDID = /^.*(?:(?:youtu\.be\/|v\/|vi\/|u\/\w\/|embed\/)|(?:(?:watch)?\?v(?:i)?=|\&v(?:i)?=))([^#\&\?]*).*/;
const { width } = Dimensions.get('window');

const VideoModal = ({ handleClose, open, urlSource }) => {
 const videoRef = useRef();
 const videoId = useRef();
 const [canGoBack, setCanGoBack] = useState(false);
 const isYoutubeVideo = _VALIDURL.test(urlSource);
 if (isYoutubeVideo) {
  videoId.current = urlSource.match(_FINDID)[1];
  }
 const handleBackButton = () => {
  videoRef.current.goBack();
  };
 return (
    <Modal
      animationType="fade"
      transparent={true}
      onRequestClose={canGoBack ? handleBackButton : handleClose}
      visible={open}
     >
      <View style={{ flex: 1 }}>
        <WebView
          style={{ width: width }}
          javaScriptEnabled={true}
          ref={videoRef}
          startInLoadingState={true}
          renderLoading={() => (
              <View style={{ flex: 1}}>
                <ActivityIndicator />
              </View>
            )}
          onNavigationStateChange={({ canGoBack }) => {
              setCanGoBack(canGoBack);
            }}
           source={{
             uri: isYoutubeVideo
             ?`https://www.youtube.com/embed/${videoId.current}/?rel=0&showinfo=0&controls=1`
             : urlSource,
            }}
         />
         {Platform.OS === 'ios' && (
            <TouchableHighlight onPress={handleClose}>
              <Text style={styles.textStyle}>Close Video</Text>
            </TouchableHighlight>
          )}
      </View>
     </Modal>
  );
};

The VideoModal component in not responsible for opening and closing the modal but showing the video to the user so it receives these 3 props. The handleClose to be able to close the modal, the open state of the modal and the urlSource.


I ll walk you though the code, we’ve done a few things here:

  • Wrapped the WebView with the Modal component, for more info about the Modal you can go here here

  • Define the _VALIDURL && _FINDID helpers to validate the video url and extract the video ID

  • Set the source property so that the webview will load

`https://www.youtube.com/embed/${videoId.current}/?rel=0&showinfo=0&controls=1`
 #For more info about the url parameters see YouTube Player Parameters
  • Added a ref property so we can easily get a hold of the WebView later on

  • Added a loading indicator by tweaking thrse two props startInLoadingState && renderLoading

Wiring Up the back button to navigate back

We've done this by:

  • Adding the onRequestClose prop to the Modal component.

The reason we use this prop is because if your app shows an opened Modal, BackHandler will not publish any events for more info see this

  • Keeping track of the navigation state thought the onNavigationStateChange prop.

We pull out the canGoBack prop and set it to our component state.This property tells us if the user has navigated past the original page we loaded and so can go back towards the original page.

  • Binding the handleBackButton function on the onRequestClose prop

Thanks to our callback, we now are able to navigate back or exit the modal depending on the canGoBack state.



Now Let's Bring in the VideoModal component into the CourseDetail


#CourseDetail.js
import VideoModal from 'components/VideoModal';

const CourseDetail = ({ navigation }) => {
 const [modalVisible, setModalVisible] = useState(false);
 const [urlSource, setUrlSource] = useState(null);

 const handleOpenModal = (url) => {
   setUrlSource(url);
   setModalVisible(true);
  };

 return (
    <View style={styles.container}>
      {modalVisible && (
	<VideoModal
          open={modalVisible}
          urlSource={urlSource}
	  handleClose={() => setModalVisible(false)}
        />
      )}
      <CourseItem
       lesson={lesson}
       handleOpenVideo={handleOpenModal}
      />
     .  .  .  .
    </View>
};


Well, I hope that helped! Right to the point! If you like this and want to support me on making more stories you can contact me on Linkedin


#reactNative #javascript #WebView #YoutubeIframe #Modals #reactNavigation #hooks #javascript #youtubePlayer


©2020 by CodeMasters and Skilltransfers