1

I'm starting with React and i have an issue.

I'm using Youtube API to catch playlist videos. With a .map method, i display all the videos thumbnails and title in cards. When i click on a card, i want to start the video (within Reactplayer) by "catching" the index of my array (in my state). Thanks a lot for the answers an advices you could provide :)

Here's my code below :

import React, { Component } from 'react'
import axios from 'axios';
import posed from 'react-pose';
import ReactPlayer from 'react-player';
import { Card, CardImg, Col, Row, CardTitle, Modal, ModalBody, ModalHeader } from 'reactstrap';
import './videos.css'

const Box = posed.div({
  hidden: { opacity: 0 },
  visible: { opacity: 1 }
});

class Videos extends Component {
  constructor () {
    super();
    this.state = {
      isVisible : true,
      videos: [],
      resultsDatas: "",
      nextPage: "",
      previousPage: "",
      videoId: "",
      search: "",
      playing: false,
      modal : false
    }
  }

componentDidMount() {
  axios.get('https://www.googleapis.com/youtube/v3/playlistItems?key=AIzaSyChOLdIP9GxDMPWjMmEnh6doR5Bdf1sGBk&playlistId=PL3-4jitn5YqtnR_mrYoz_Qb0z7frXZcW6&type=video&showinfo=0&iv_load_policy=3&part=snippet,id&order=date&maxResults=24')
  .then((result) => { 
    this.setState({
      videos: result.data.items,
      resultsDatas: result.data,
      nextPage: result.data.nextPageToken});
      console.log(this.state.videos);

      this.state.videos.map((item) => {
        if(item.snippet.title.length > 38) {
          return (item.snippet.title=`${item.snippet.title.slice(0,37)}... `);
        }
        })
    }
  )

  setTimeout(() => {this.setState({ isVisible: !this.state.isVisible }); 
  }, 400);

}


nextPage = () => {
  axios.get(`https://www.googleapis.com/youtube/v3/playlistItems?key=AIzaSyChOLdIP9GxDMPWjMmEnh6doR5Bdf1sGBk&playlistId=PL3-4jitn5YqtnR_mrYoz_Qb0z7frXZcW6&type=video&part=snippet,id&order=date&maxResults=24&pageToken=${this.state.nextPage}`)
  .then((result) => { 
    this.setState({
      nextPage: result.data.nextPageToken,
      previousPage: result.data.prevPageToken,
      videos: result.data.items,
      resultsDatas: result.data
    });
  })
}

previousPage = () => {
  axios.get(`https://www.googleapis.com/youtube/v3/playlistItems?key=AIzaSyChOLdIP9GxDMPWjMmEnh6doR5Bdf1sGBk&playlistId=PL3-4jitn5YqtnR_mrYoz_Qb0z7frXZcW6&type=video&part=snippet,id&order=date&maxResults=24&pageToken=${this.state.previousPage}`)
  .then((result) => { 
    this.setState({
      nextPage: result.data.nextPageToken,
      previousPage: result.data.prevPageToken,
      videos: result.data.items,
      resultsDatas: result.data});
  })
}

//For search function
inputChange = (event) => {
  this.setState({search: event.target.value })
}


playPause = (index) => {
  let element = document.getElementById(`play-pause${index}`);
  if (element.requestFullscreen) {
    this.setState({playing: !this.state.playing})
  }
}

toggleModal = () => {
  this.setState({
    modal: !this.state.modal
  });
}

  render() {
    let mapedVideos = this.state.videos.filter(
      (item) => {
        return item.snippet.title.toLowerCase().indexOf(this.state.search) !==-1;
      }
    );
  
    return (
      <div>

        <Box pose={this.state.isVisible ? 'hidden' : 'visible'}>
        <Row className="custom-videos-row mb-5">
          {mapedVideos.map((item, index) => {
            return (
              <Col className="custom-videos-col" lg="3" md="4" sm="6" key={index}> 
                <Card className="card-wrapper" onClick={() => {this.toggleModal()}}>
                  <CardImg className="video-thumbnail" src={item.snippet.thumbnails.medium.url} alt="thumb"></CardImg>
                    <CardTitle className="video-card-title pl-2"><img className="play-picto" src={process.env.PUBLIC_URL + '/images/play_L.png'} alt="play-picto"/>{item.snippet.title}
                      </CardTitle>
                </Card>
              </Col>
            );
            })}

            <Modal role="dialog" isOpen={this.state.modal} toggle={this.toggleModal}>
              <ModalHeader  className="custom-modal-header" toggle={this.toggleModal}>
                <img src={process.env.PUBLIC_URL + './images/logo.png'} alt="La Baule TV logo" className="LBTV-logo"></img>
                <span className="ml-2">La Baule</span></ModalHeader>
                <ModalBody>
                <ReactPlayer className="video-player"
                          url={'https://www.youtube.com/watch?v=T_IUcX17GXE&t=7s'}
                          playing= {true}
                          config={{
                            youtube: {
                              playerVars: { 
                                modestbranding: 1,
                                controls: 1,
                                rel: 0
                              }
                            }}}
                          />
                  </ModalBody>
              </Modal>
        </Row>
        </Box>
      </div>
    )
  }
}

export default Videos;

1 Answers1

1

To play the video which you clicked, you need to get the videoId of the particular video and change the url in the ReactPlayer to look something like this https://www.youtube.com/watch?v=xxxxxxxxxxx.

Create a function called onThumbnailClick or some other name which is the function to be executed when the thumbnail is clicked. So instead of <Card className="card-wrapper" onClick={() => {this.toggleModal()}}> do something like <Card className="card-wrapper" onClick={() => {this.onClickThumbnail(index)}}>. (We have the index of the video from the map used earlier)

What this function should do is to set the state with the url of the video. We are passing the index to the funciton. Get from this.state.videos, this.state.videos[index] which would be the clicked video.

We know the videoId of that particular video is in the videos state. this.state.videos[index].snippet.resourceId.videoId will give you the videoId. Set the state with that videoId and then open the modal.

onClickThumbnail = (index) => {
  this.setState({
    clickedVideoId: this.state.videos[index].snippet.resourceId.videoId
  })
  this.toggleModal()
}

and change ReactPlayer url to

url={`https://www.youtube.com/watch?v=${this.state.clickedVideoId}`}
illiteratewriter
  • 4,155
  • 1
  • 23
  • 44
  • Thanks a lot for the quick and complete answer :) Il will try this this evening ;) – Matthieu PETIT Feb 09 '19 at 18:04
  • If it helped you can upvote and also mark as answer by clicking on the tick mark next to the answer :) – illiteratewriter Feb 09 '19 at 18:07
  • You seems to know youtube API :) I have another question...maybee, i know some things about that ;) I made a search button and i found a function to do that....but i'm stuck because of the 50 videos items of youtube API....i don't know if it exists a method to do a search in all videos of a youtube playlist...... – Matthieu PETIT Feb 09 '19 at 20:11
  • I don't know the api, i opened one of the items in the array of videos and found that id. Refer this https://stackoverflow.com/questions/25953068/how-can-i-search-inside-a-youtube-playlist – illiteratewriter Feb 10 '19 at 04:40