reactjshtml5-audioweb-audio-apihowler.js

Issue with pausing audio in Howler and react


Please have a look at this simple code -

  const PlayPause = () => {
    const sound = new Howl({
      src: [
        "https://..." // I have a link to an mp3 file stored in an S3 bucket
      ],
      loop: true,
      volume: 0.5
    })

    const [ isPlaying, setIsPlaying ] = useState(false)

    const togglePlay = () => {
          if (isPlaying) {
              sound.pause()
              setIsPlaying(false)
          } else {
              sound.play()
              setIsPlaying(true)
          }
    }

    return (
      <button onClick={ togglePlay }>Press me</button>
    )
  }

  export default PlayPause

I'm trying to create a simple play/pause toggle for a Howler audio file streaming from the web. All my react functions are working fine. When I click on the div, play works correctly but pause doesn't. In fact, it actually plays multiple instances of the audio file whenever I click on play. Is there something wrong I'm doing here?


Solution

  • You have declared 'sound' inside the const PlayPause. For sound.pause() to work the access of 'sound' should be global. Do it like this:

    let sound = new Howl({
      src: [
        "https://...", // I have a link of an mp3 file stored in an S3 bucket
      ],
      loop: false,
      volume: 0.5,
    });
    
    const PlayPause = () => {
      const [isPlaying, setIsPlaying] = useState(false);
    
      return (
        <button
          className="volume main-box dummy-abs"
          onClick={() => {
            // Toggles play / pause
    
            if (isPlaying) {
              sound.pause();
              setIsPlaying(false);
            } else {
              sound.play();
              setIsPlaying(true);
            }
            console.log("isPlaying", isPlaying);
          }}
        >
          Press Me
        </button>
      );
    };
    
    export default PlayPause;
    

    Hopefully it will work.

    You can use react-howler if you are not comfortable with global access. With react-howler you can do it like this:

    import ReactHowler from "react-howler";
    
    const PlayPause = () => {
      const [playpause, setPlaypause] = useState(false);
      return (
        <div>
          <ReactHowler
            src="https://..."
            playing={playpause}
            //ref={(ref) => (this.player = ref)}
          />
          <button onClick={() => setPlaypause(!playpause)}> Press Me</button>
        </div>
      );
    };
    
    export default PlayPause;