Search code examples
reactjsreact-hooksreact-player

Rendering different youtube videos on button click


I created a react app where I display different video games and the app decides which game to play. I also have a file where I stored the data of video games. The goal I'm trying to achieve is to render the youtube video trailer of the corresponding video game when clicking on a button while using React Hooks. I've been using the npm package react-player. If someone could help, I'd appreciate it.

This is the code for the Video Game component:

import React from 'react';
import { Button, message } from 'antd';
import { Row, Col } from 'antd';
import GameEntry from '../GameEntry';
import Games from '../Games';

function VideoGameSection() {
    const chooseGame = () => {
        var randomGameTitle = [
            'Gears 5',
            'Halo',
            'Hellblade',
            'It takes two',
            'A Plague Tale',
            'Psychonauts',
            'Twelve Minutes',
            'Ori',
            'Streets of Rage',
            'Last of Us',
            'Boodborne',
            'Geenshin Impact',
            'Dragon Ball Z:KAKAROT',
            'Ghost Tsushima',
            'Naruto',
            'Overcooked',
            'Horizon',
            'Tomb Raider',
            'Uncharted',
            'Person 5 Royal',
            'Ratchet',
            'Spider-Man',
        ];

        var randomIndex = Math.floor(Math.random() * randomGameTitle.length);

        return message.info(
            'The game you will play is: ' + randomGameTitle[randomIndex] + '.',
        );
    };

    return (
        <div id="video-game" className="block bgGray">
            <div className="container-fluid">
                <div className="titleHolder">
                    <h2>Video Games</h2>
                    <p>A list of current games</p>
                    <div className="site-button-ghost-wrapper">
                        <Button
                            className="gameButton"
                            type="primary"
                            danger
                            ghost
                            onClick={chooseGame}
                        >
                            Pick for me
                        </Button>
                    </div>
                </div>
                <Row gutter={[16, 24]}>
                    {Games.map((videogame, i) => (
                        <Col span={8}>
                            <GameEntry
                                id={i}
                                key={i}
                                title={videogame.title}
                                imgURL={videogame.imgURL}
                                description={videogame.console}
                            />
                        </Col>
                    ))}
                </Row>
            </div>
        </div>
    );
}

export default VideoGameSection;

This is the code for my game entry component:

import React, { useState } from 'react';
import { Card, Button, Modal } from 'antd';
import YoutubeSection from './Home/YoutubeSection';

const { Meta } = Card;

function GameEntry(props) {
    const [isModalVisible, setIsModalVisible] = useState(false);

    const showModal = () => {
        setIsModalVisible(true);
    };

    const handleClose = () => {
        setIsModalVisible(false);
    };

    const handleCancel = () => {
        setIsModalVisible(false);
    };

    return (
        <div>
            <Card
                className="gameCard"
                hoverable
                cover={<img className="cardImg" alt={props.title} src={props.imgURL} />}
            >
                <div className="cardTitle">
                    <Meta title={props.title} description={props.description} />
                </div>
                <>
                    <Button
                        className="trailerButton"
                        type="primary"
                        block
                        style={{
                            color: '#fff',
                            borderColor: '#fff',
                            backgroundColor: '#e6544f',
                        }}
                        onClick={showModal}
                    >
                        Click for trailer
                    </Button>
                    <Modal
                        title={props.title}
                        width={'725px'}
                        visible={isModalVisible}
                        onOk={handleClose}
                        onCancel={handleCancel}
                    >
                        <YoutubeSection />
                    </Modal>
                </>
            </Card>
        </div>
    );
}

export default GameEntry;

This is the code for the youtube component:

import React, { useState } from 'react';
import ReactPlayer from 'react-player';

function YoutubeSection(props) {
    return (
        <div className="container-fluid">
            <ReactPlayer
                // url={videoTrailer}
                muted={false}
                playing={true}
                controls={true}
            />
        </div>
    );
}

export default YoutubeSection;

example of data file:

const Games = [
    {
        id: 1,
        title: 'Gears 5',
        imgURL: '../Images/gears-5.jpeg',
        console: 'Xbox',
        videoID: 'SEpWlFfpEkU&t=7s',
    },

Solution

  • You can keep a single Modal component and use it for that.

    ModalView.js

    import React, { useState } from "react";
    import YoutubeSection from "./YoutubeSection";
    import { Modal } from "antd";
    
    const ModalView = ({
      title,
      isModalVisible,
      handleClose,
      handleCancel,
      videoID
    }) => {
      return (
        <Modal
          title={title}
          width={"725px"}
          visible={isModalVisible}
          onOk={handleClose}
          onCancel={handleCancel}
        >
          <YoutubeSection videoID={videoID} />
        </Modal>
      );
    };
    
    export default ModalView;
    

    Move the ModalView and its state, control functions to the VideoGameSection.

    VideoGameSection.js

    import React, { useState } from "react";
    import { Button, message } from "antd";
    import { Row, Col } from "antd";
    import GameEntry from "./GameEntry";
    import Games from "./Games";
    import ModalView from "./ModalView";
    
    function VideoGameSection() {
      const [isModalVisible, setIsModalVisible] = useState(false);
      const [currentVideoID, setCurrentVideoID] = useState("");
    
      const showModal = () => {
        setIsModalVisible(true);
      };
    
      const handleClose = () => {
        setIsModalVisible(false);
      };
    
      const handleCancel = () => {
        setIsModalVisible(false);
      };
    
      const chooseGame = () => {
        var randomGameTitle = [
          "Gears 5",
          "Halo",
          "Hellblade",
          "It takes two",
          "A Plague Tale",
          "Psychonauts",
          "Twelve Minutes",
          "Ori",
          "Streets of Rage",
          "Last of Us",
          "Boodborne",
          "Geenshin Impact",
          "Dragon Ball Z:KAKAROT",
          "Ghost Tsushima",
          "Naruto",
          "Overcooked",
          "Horizon",
          "Tomb Raider",
          "Uncharted",
          "Person 5 Royal",
          "Ratchet",
          "Spider-Man"
        ];
    
        var randomIndex = Math.floor(Math.random() * randomGameTitle.length);
    
        return message.info(
          "The game you will play is: " + randomGameTitle[randomIndex] + "."
        );
      };
    
      return (
        <div id="video-game" className="block bgGray">
          <div className="container-fluid">
            <div className="titleHolder">
              <h2>Video Games</h2>
              <p>A list of current games</p>
              <div className="site-button-ghost-wrapper">
                <Button
                  className="gameButton"
                  type="primary"
                  danger
                  ghost
                  onClick={chooseGame}
                >
                  Pick for me
                </Button>
              </div>
            </div>
            <Row gutter={[16, 24]}>
              {Games.map((videogame, i) => (
                <Col span={8}>
                  <GameEntry
                    id={i}
                    key={i}
                    title={videogame.title}
                    imgURL={videogame.imgURL}
                    description={videogame.console}
                    videoID={videogame.videoID}
                    setCurrentVideoID={setCurrentVideoID}
                    showModal={showModal}
                  />
                </Col>
              ))}
              <ModalView
                videoID={currentVideoID}
                handleClose={handleClose}
                isModalVisible={isModalVisible}
              />
            </Row>
          </div>
        </div>
      );
    }
    
    export default VideoGameSection;
    
    

    Access the videoID passed via ModalView. You can save gameId instead of videoID to get any other info of the game Ex:title. YoutubeSection.js

    import React, { useState } from "react";
    import ReactPlayer from "react-player";
    
    function YoutubeSection(props) {
      return (
        <div className="container-fluid">
          <ReactPlayer
            url={`https://www.youtube.com/watch?v=${props.videoID}`}
            muted={false}
            playing={true}
            controls={true}
          />
        </div>
      );
    }
    
    export default YoutubeSection;
    

    GameEntry.js

    import React, { useState } from "react";
    import { Card, Button, Modal } from "antd";
    import YoutubeSection from "./YoutubeSection";
    
    const { Meta } = Card;
    
    function GameEntry(props) {
      return (
        <div>
          <Card
            className="gameCard"
            hoverable
            cover={<img className="cardImg" alt={props.title} src={props.imgURL} />}
          >
            <div className="cardTitle">
              <Meta title={props.title} description={props.description} />
            </div>
            <>
              <Button
                className="trailerButton"
                type="primary"
                block
                style={{
                  color: "#fff",
                  borderColor: "#fff",
                  backgroundColor: "#e6544f"
                }}
                onClick={() => {
                  props.setCurrentVideoID(props.videoID);
                  props.showModal();
                }}
              >
                Click for trailer
              </Button>
            </>
          </Card>
        </div>
      );
    }
    
    export default GameEntry;
    
    

    Code sandbox => https://codesandbox.io/s/flamboyant-dan-z0kc0?file=/src/ModalView.js