unmute react-player when fullscreen is toggled from outer component

3.4k views Asked by At

I have a VideoItem- and a Player-component

In VideoList a button is clicked and is going to fullscreen mode (is working as expected) I will unmute player when fullscreen is clicked.

How can I pass down a "mute" change from VideoList to Player? In my Player I also have a "Unmute" button (which is also working as expected:

This is what I have so far

VideoItem.jsx

import React, { useRef, useState, useEffect } from "react"
import { findDOMNode } from "react-dom"
import screenfull from "screenfull"
import VideoPlayer from "./VideoPlayer"

const VideoList = (videos) => {
  const ref = useRef()

  const toggleFullScreen = () => {
    screenfull.request(findDOMNode(ref.current))
  }

  const unMute = () => {
    console.log("Should pass Mute state to player", muted)
  }
  return (
   <>
     <VideoPlayer
            ref={ref}
            mute={muted}
            videoURL={videoUrl}
     />
     <a
       href="#"
       onClick={e => {
         e.preventDefault()
         unMute()
         toggleFullScreen()
       }}
     >
      Show Fullscreen
     </a>
  )
}

Player.jsx

import React, { forwardRef, useState, useEffect } from "react"
import ReactPlayer from "react-player"
const VideoPlayer = forwardRef((props, ref, mute) => {
  let [muteState, setMuteState] = useState(true)

  return (
    <>
      <i className={`fal fa-volume-${muteState ? "up" : "mute"}`}
         onClick={() => {
           setMuteState(!muteState)
         }}
      />
      <ReactPlayer
          ref={ref}
          muted={muteState}
          loop={true}
          playing={true}
          url={props.videoURL}
        />
    </>
  )
}

Thank you!

1

There are 1 answers

0
trixn On BEST ANSWER

When you attempt to set the state from the parent this usually is an indicator that you should move the state up and make the child controlled by the parent:

const VideoList = (videos) => {
  const player = useRef();
  const [muted, setMuted] = useState(true);
  const [fullscreen, setFullscreen] = useState(false);

  const handleToggleMute = () => setMuted(current => !current);

  const handleFullscreen = event => {
    event.preventDefault();
    setMuted(false);
    setFullscreen(true);
  };

  return (
   <>
     <VideoPlayer
       ref={ref}
       muted={muted}
       fullscreen={fullscreen}
       videoURL={videoUrl}
       onToggleMute={handleToggleMute}
     />
     <a href="#" onClick={handleFullscreen}>Show Fullscreen</a>
  )
}

Also I would use useEffect together with another state fullscreen to avoid having to forward a ref of the video player.

const VideoPlayer = ({videoURL, muted, fullscreen, onToggleMute}) => {
  const playerRef = useRef();

  useEffect(() => {
      if (fullscreen) {
        const videoElem = playerRef.current.getInternalPlayer();
        screenfull.request(videoElem);
      }
  }, [fullscreen]);

  return (
    <>
      <i 
        className={`fal fa-volume-${muted ? "up" : "mute"}`}
        onClick={onToggleMute}
      />
      <ReactPlayer
        ref={playerRef}
        muted={muted}
        loop={true}
        playing={true}
        url={videoURL}
      />
    </>
  )
}