React YouTube Video Embed in Image Gallery Tutorial

In this tutorial, you will learn how to embed Youtube or any video in the gallery slider supporting their thumbnails. We will be creating a react class component to show a video carousel where you can embed video players.

By using a very simple yet powerful Image/ Video gallery plugin, you can display media content in auto sliding and responsive carousel.

We will use the react0image-gallery plugin to achieve the video player carousel feature on React page components. This plugin supports a number of features like:

  • Image and Video Slider
  • Autoplay slider
  • Fullscreen View switch
  • Responsive and touch screen support

You can check out the image slider carousel tutorial here. In this guide you will learn how to create a video slider component by following a few easy steps:

How to add a Video Player Gallery in React JS app?

Step 1 – Create a React App

Step 2 – Install React Image Gallery Library

Step 3 – Create MyGallery Component

Step 4 – Add Image Gallery

Step 5 – Use Image Gallery in App Component

Step 6 – Run Application

 

Create a React App

Before creating the React app, you need to install the create-react-app to create new React application.

npm install create-react-app --global

 

Now create a new React application by executing the npx command and providing the app name:

npx create-react-app react-app

 

Open the application directory then you can open it in VS code:

cd react-app

code .

 

Install React Image Gallery Library

After creating the application, we will install the react image gallery library by executing the below npm command:

npm install react-image-gallery

 

Create MyVideoSlider Component

Head towards the src folder at the root and create a components folder with a file named MyVideoSlider.js. Next, update the file with the following content:

import React from 'react';

class MyVideoSlider extends React.Component {
  constructor() {
    super();
  }
  render() {
    return <div>MyVideoSlider</div>;
  }
}
export default MyVideoSlider;

 

 

Add Video Player Slider

Thereafter, we will update the MyVideoSlider.js file by importing the SCSS or CSS style and its MyGallery component. We will also add a const object to define the Image path and their respective thumbnails and youtube video links:

import React from 'react';
import ImageGallery from 'react-image-gallery';
import 'react-image-gallery/styles/scss/image-gallery.scss';

const PREFIX_URL =
  'https://raw.githubusercontent.com/xiaolin/react-image-gallery/master/static/';

class MyVideoSlider extends React.Component {
  constructor() {
    super();
    this.state = {
      showIndex: false,
      showBullets: true,
      infinite: true,
      showThumbnails: true,
      showFullscreenButton: true,
      showGalleryFullscreenButton: true,
      showPlayButton: true,
      showGalleryPlayButton: true,
      showNav: true,
      isRTL: false,
      slideDuration: 450,
      slideInterval: 2000,
      slideOnThumbnailOver: false,
      thumbnailPosition: 'bottom',
      showVideo: {},
      useWindowKeyDown: true,
    };

    this.images = [
      {
        thumbnail: `https://i3.ytimg.com/vi/sGvh-WJjK60/hqdefault.jpg`,
        original: `https://i3.ytimg.com/vi/sGvh-WJjK60/maxresdefault.jpg`,
        embedUrl:
          'https://www.youtube.com/embed/sGvh-WJjK60?autoplay=1&showinfo=0',
        description: 'Render custom slides (such as videos)',
        renderItem: this._renderVideo.bind(this),
      },
      {
        thumbnail: `https://i3.ytimg.com/vi/tYGh2qnCl9I/hqdefault.jpg`,
        original: `https://i3.ytimg.com/vi/tYGh2qnCl9I/maxresdefault.jpg`,
        embedUrl:
          'https://www.youtube.com/embed/tYGh2qnCl9I?autoplay=1&showinfo=0',
        description: 'Render custom slides (such as videos)',
        renderItem: this._renderVideo.bind(this),
      },
      {
        original: `${PREFIX_URL}1.jpg`,
        thumbnail: `${PREFIX_URL}1t.jpg`,
        originalClass: 'featured-slide',
        thumbnailClass: 'featured-thumb',
        description: 'Custom class for slides & thumbnails',
      },
    ].concat(this._getStaticImages());
  }

  _onImageClick(event) {
    console.debug(
      'clicked on image',
      event.target,
      'at index',
      this._imageGallery.getCurrentIndex()
    );
  }

  _onImageLoad(event) {
    console.debug('loaded image', event.target.src);
  }

  _onSlide(index) {
    this._resetVideo();
    console.debug('slid to index', index);
  }

  _onPause(index) {
    console.debug('paused on index', index);
  }

  _onScreenChange(fullScreenElement) {
    console.debug('isFullScreen?', !!fullScreenElement);
  }

  _onPlay(index) {
    console.debug('playing from index', index);
  }

  _handleInputChange(state, event) {
    if (event.target.value > 0) {
      this.setState({ [state]: event.target.value });
    }
  }

  _handleCheckboxChange(state, event) {
    this.setState({ [state]: event.target.checked });
  }

  _handleThumbnailPositionChange(event) {
    this.setState({ thumbnailPosition: event.target.value });
  }

  _getStaticImages() {
    let images = [];
    for (let i = 2; i < 4; i++) {
      images.push({
        original: `${PREFIX_URL}${i}.jpg`,
        thumbnail: `${PREFIX_URL}${i}t.jpg`,
      });
    }

    return images;
  }

  _resetVideo() {
    this.setState({ showVideo: {} });

    if (this.state.showPlayButton) {
      this.setState({ showGalleryPlayButton: true });
    }

    if (this.state.showFullscreenButton) {
      this.setState({ showGalleryFullscreenButton: true });
    }
  }

  _toggleShowVideo(url) {
    this.state.showVideo[url] = !Boolean(this.state.showVideo[url]);
    this.setState({
      showVideo: this.state.showVideo,
    });

    if (this.state.showVideo[url]) {
      if (this.state.showPlayButton) {
        this.setState({ showGalleryPlayButton: false });
      }

      if (this.state.showFullscreenButton) {
        this.setState({ showGalleryFullscreenButton: false });
      }
    }
  }

  _renderVideo(item) {
    return (
      <div>
        {this.state.showVideo[item.embedUrl] ? (
          <div className="video-wrapper">
            <a
              className="close-video"
              onClick={this._toggleShowVideo.bind(this, item.embedUrl)}
            ></a>
            <iframe
              width="560"
              height="315"
              src={item.embedUrl}
              frameBorder="0"
              allowFullScreen
            ></iframe>
          </div>
        ) : (
          <a onClick={this._toggleShowVideo.bind(this, item.embedUrl)}>
            <div className="play-button"></div>
            <img className="image-gallery-image" src={item.original} />
            {item.description && (
              <span
                className="image-gallery-description"
                style={{ right: '0', left: 'initial' }}
              >
                {item.description}
              </span>
            )}
          </a>
        )}
      </div>
    );
  }

  render() {
    return (
      <section className="app">
        <ImageGallery
          ref={(i) => (this._imageGallery = i)}
          items={this.images}
          onClick={this._onImageClick.bind(this)}
          onImageLoad={this._onImageLoad}
          onSlide={this._onSlide.bind(this)}
          onPause={this._onPause.bind(this)}
          onScreenChange={this._onScreenChange.bind(this)}
          onPlay={this._onPlay.bind(this)}
          infinite={this.state.infinite}
          showBullets={this.state.showBullets}
          showFullscreenButton={
            this.state.showFullscreenButton &&
            this.state.showGalleryFullscreenButton
          }
          showPlayButton={
            this.state.showPlayButton && this.state.showGalleryPlayButton
          }
          showThumbnails={this.state.showThumbnails}
          showIndex={this.state.showIndex}
          showNav={this.state.showNav}
          isRTL={this.state.isRTL}
          thumbnailPosition={this.state.thumbnailPosition}
          slideDuration={parseInt(this.state.slideDuration)}
          slideInterval={parseInt(this.state.slideInterval)}
          slideOnThumbnailOver={this.state.slideOnThumbnailOver}
          additionalClass="app-image-gallery"
          useWindowKeyDown={this.state.useWindowKeyDown}
        />

        <div className="app-sandbox">
          <div className="app-sandbox-content">
            <h2 className="app-header">Settings</h2>

            <ul className="app-buttons">
              <li>
                <div className="app-interval-input-group">
                  <span className="app-interval-label">Play Interval</span>
                  <input
                    className="app-interval-input"
                    type="text"
                    onChange={this._handleInputChange.bind(
                      this,
                      'slideInterval'
                    )}
                    value={this.state.slideInterval}
                  />
                </div>
              </li>

              <li>
                <div className="app-interval-input-group">
                  <span className="app-interval-label">Slide Duration</span>
                  <input
                    className="app-interval-input"
                    type="text"
                    onChange={this._handleInputChange.bind(
                      this,
                      'slideDuration'
                    )}
                    value={this.state.slideDuration}
                  />
                </div>
              </li>

              <li>
                <div className="app-interval-input-group">
                  <span className="app-interval-label">
                    Thumbnail Bar Position
                  </span>
                  <select
                    className="app-interval-input"
                    value={this.state.thumbnailPosition}
                    onChange={this._handleThumbnailPositionChange.bind(this)}
                  >
                    <option value="bottom">Bottom</option>
                    <option value="top">Top</option>
                    <option value="left">Left</option>
                    <option value="right">Right</option>
                  </select>
                </div>
              </li>
            </ul>

            <ul className="app-checkboxes">
              <li>
                <input
                  id="infinite"
                  type="checkbox"
                  onChange={this._handleCheckboxChange.bind(this, 'infinite')}
                  checked={this.state.infinite}
                />
                <label htmlFor="infinite">allow infinite sliding</label>
              </li>
              <li>
                <input
                  id="show_fullscreen"
                  type="checkbox"
                  onChange={this._handleCheckboxChange.bind(
                    this,
                    'showFullscreenButton'
                  )}
                  checked={this.state.showFullscreenButton}
                />
                <label htmlFor="show_fullscreen">show fullscreen button</label>
              </li>
              <li>
                <input
                  id="show_playbutton"
                  type="checkbox"
                  onChange={this._handleCheckboxChange.bind(
                    this,
                    'showPlayButton'
                  )}
                  checked={this.state.showPlayButton}
                />
                <label htmlFor="show_playbutton">show play button</label>
              </li>
              <li>
                <input
                  id="show_bullets"
                  type="checkbox"
                  onChange={this._handleCheckboxChange.bind(
                    this,
                    'showBullets'
                  )}
                  checked={this.state.showBullets}
                />
                <label htmlFor="show_bullets">show bullets</label>
              </li>
              <li>
                <input
                  id="show_thumbnails"
                  type="checkbox"
                  onChange={this._handleCheckboxChange.bind(
                    this,
                    'showThumbnails'
                  )}
                  checked={this.state.showThumbnails}
                />
                <label htmlFor="show_thumbnails">show thumbnails</label>
              </li>
              <li>
                <input
                  id="show_navigation"
                  type="checkbox"
                  onChange={this._handleCheckboxChange.bind(this, 'showNav')}
                  checked={this.state.showNav}
                />
                <label htmlFor="show_navigation">show navigation</label>
              </li>
              <li>
                <input
                  id="show_index"
                  type="checkbox"
                  onChange={this._handleCheckboxChange.bind(this, 'showIndex')}
                  checked={this.state.showIndex}
                />
                <label htmlFor="show_index">show index</label>
              </li>
              <li>
                <input
                  id="is_rtl"
                  type="checkbox"
                  onChange={this._handleCheckboxChange.bind(this, 'isRTL')}
                  checked={this.state.isRTL}
                />
                <label htmlFor="is_rtl">is right to left</label>
              </li>
              <li>
                <input
                  id="slide_on_thumbnail_hover"
                  type="checkbox"
                  onChange={this._handleCheckboxChange.bind(
                    this,
                    'slideOnThumbnailOver'
                  )}
                  checked={this.state.slideOnThumbnailOver}
                />
                <label htmlFor="slide_on_thumbnail_hover">
                  slide on mouse over thumbnails
                </label>
              </li>
              <li>
                <input
                  id="use_window_keydown"
                  type="checkbox"
                  onChange={this._handleCheckboxChange.bind(
                    this,
                    'useWindowKeyDown'
                  )}
                  checked={this.state.useWindowKeyDown}
                />
                <label htmlFor="use_window_keydown">use window keydown</label>
              </li>
            </ul>
          </div>
        </div>
      </section>
    );
  }
}

export default MyVideoSlider;

Above we have various configuration control actions and video embed functions. Moreover, various video controls like play, stop, render video etc.

 

Use Video Player Gallery in App Component

Now, we will import the MyVideoSlider.js component into the main App to render it in our application. Open the App.js file and update it with the following code:

import * as React from 'react';
import MyVideoSlider from './components/MyVideoSlider';
import './style.css';

export default function App() {
  return (
    <div>
      <h1>
        React Video Player Gallery Example
      </h1>
      <MyVideoSlider />
    </div>
  );
}

 

Run Application

We are ready to run our application by hitting the following command:

npm start

It will start the development server and run our app at the following URL:

http://localhost:3000/