Home > Mobile >  when displaying videos from an array using .map(), button plays ALL videos instead of selected
when displaying videos from an array using .map(), button plays ALL videos instead of selected

Time:09-16

I’m displaying an array of YouTube videos in this component (using react-player) and have gotten them to play when the custom play button is clicked, but it plays (and pauses) all of them instead of the currently selected item.

I’m using the useRef hook, and am having trouble figuring out how to reference a selected video and play only that video (using key and/or index):

Note: if I remove the useRef hook and ref from ReactPlayer, the videos do not play at all

import React, {useState, useRef} from 'react';
import {useStaticQuery, graphql} from 'gatsby';
import ReactPlayer from 'react-player';
import {Button} from '../Buttons/Button';
import './videos.scss';
import '../../Molecules/Cards/cards.scss';

const VideoCards = () => {
   const { allVideoCardsJson } = useStaticQuery(
        graphql`
          query VideoQuery {
            allVideoCardsJson {
                edges {
                  node {
                    title
                    source
                  }
                }
              }
        }
    `)

    let videoRef = useRef();
    const [isPlaying, setIsPlaying] = useState(false);
  
    const playVideo = () => {
      // this plays/pauses all of the videos
      setIsPlaying(!isPlaying);

      // this plays the last video in the array
      //videoRef.current.getInternalPlayer().playVideo()
    }

    return (
        <div className="card-container__videos"> 
                          
          {allVideoCardsJson.edges.map(({node, index}) => ( 
          <div className="video-card" key={index} isPlaying={isPlaying}>
               <ReactPlayer 
                  ref={videoRef}
                  url={node.source}
                  width="100%"
                  pip={true} 
                  controls={true}
                  playing={isPlaying}
                ></ReactPlayer>
              
                <Button onClick={playVideo} style={{zIndex:'200'}} label="Play Video"></Button>
                </div>
          
               ))} 
            </div>
           
    );
};

export default VideoCards;

UPDATE: I was able to move the eventHandler function into the Button and receive the same results (playing/pausing all videos) but I'm still having trouble figuring out how to reference a key/unique id and use it in the function:

<Button onClick={() => {
                 if(isPlaying) {
                   setIsPlaying(false);
                 } else {
                   setIsPlaying(true);
                 }
               }}  label="Play Video"></Button>

CodePudding user response:

isPlaying is set outside of the map, and is not specific to any mapped index.

So you need to change isPlaying to be specific to the mapped element. Create an object based off allVideoCardsJson that contains boolean values for each item. Then, update them in playVideo by making it take the index or some identifier as an argument.

CodePudding user response:

Instead of a Boolean, store the index of the video that is playing in isPlaying

Change the Button onClick to: onClicK={() => playVideo(index)}

Change the playVideo function:

const playVideo = i => setIsPlaying(i)

In ReactPlayer change the playing prop: playing={isPlaying === index}

You could probably remove the isPlaying prop from the containing div, not sure what that’s accomplishing

  • Related