Youtube iframe API is not stopping the video for custom keys clicked in react js

Viewed 733

I am setting up a project where the youtube videos will be auto-played and the user will pause/play the video by only using the keyboard hence I have implemented keyup event handler to listen to the keystrokes and its working but I am unable to stop the video by pressing the space bar.

I am using youtube-Iframe-API

Parent Component

import React, { useState, useEffect, useRef } from 'react';
import './style.css';
import ChildCOmp from './ChildCOmp';

export default function App() {
  const [iframeSrc, setIframeCont] = useState(false);
  const [spaceBtnClicked, setSpaceBtnClick] = useState(false);

  useEffect(() => {
    setIframeCont('M7lc1UVf-VE');

    document.addEventListener('keyup', function(e) {
      if (e.code === 'Space') {
        debugger;
        setSpaceBtnClick(prevState => ({
          ...prevState,
          spaceBtnClicked: !prevState
        }));
      }
    });
  }, []);

  return (
    <div>
      <h1>Hello StackBlitz!</h1>
      <ChildCOmp iframeSrc={iframeSrc} spaceBtnClicked={spaceBtnClicked} />
    </div>
  );
}

On this parent, I am sending youtube id(here it's static but in reality it could be dynamic) and the space bar indication state.

Child Component - where youtube API referred and video would be auto-played

import React, { useState, useEffect, useRef } from 'react';

let player = '';

export default function ChildCOmp({ iframeSrc, spaceBtnClicked }) {
  useEffect(() => {
    //I need to pause/play the video by pressing space button which is coming form parent spaceBtnClicked
    if (iframeSrc) {
      if (!window.YT) {
        // If not, load the script asynchronously
        const tag = document.createElement('script');
        tag.src = 'https://www.youtube.com/iframe_api';

        // onYouTubeIframeAPIReady will load the video after the script is loaded
        window.onYouTubeIframeAPIReady = loadVideo;

        const firstScriptTag = document.getElementsByTagName('script')[0];
        firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
      } else {
        // If script is already there, load the video directly
        loadVideo();
      }
    }
  });

  const loadVideo = () => {
    //const { iframeSrc } = props;

    // the Player object is created uniquely based on the id in props
    player = new window.YT.Player(`youtube-player-${iframeSrc}`, {
      videoId: iframeSrc,
      height: '600',
      width: '870',
      playerVars: {
        autoplay: 1
      },
      events: {
        onReady: onPlayerReady,
        onStateChange: onPlayerStateChange
      }
    });
  };

  const onPlayerReady = event => {
    event.target.setVolume(100);
    event.target.playVideo();
    if (spaceBtnClicked) console.log(event); // want to stop the video if space bar clicked
  };

  const onPlayerStateChange = e => {
    if (iframeSrc.id && iframeCont) {
      if (spaceBtnClicked) stopVideo();
      else {
        startVideo();
      }
    }
    console.log(e.target);
  };

  function stopVideo() {
    player.stopVideo();
  }

  function startVideo() {
    player.startVideo();
  }

  return (
    <div>
      <div id={`youtube-player-${iframeSrc}`} className="iframeYtExternal" />
    </div>
  );
}

My requirement is, pause and play the video again by pressing the space bar and I have to send that space bar state from parent to child. I did it with the physical play/pause buttons but I am unable to do if the user press the space bar since its a requirement

I tried to stop it but it shows the player is not defined when the space bar state updates.

DEMO code available here

0 Answers
Related