Home > Software design >  Unable to pause React audio
Unable to pause React audio

Time:01-06

import { useState } from "react";

function Music(){

  const [pauseToggle, setpauseToggle] = useState(false)

  const music = new Audio(require(`./Alan.mp3`));
  console.log(music);
  let isPlaying = false;

  const player = () => {
    pauseToggle ? setpauseToggle(false) : setpauseToggle(true);
    if(isPlaying){
      music.pause();
      isPlaying = false;
    }else{
      music.play();
      isPlaying = true;
    }
  }

  return(
    <div>
      <button onClick={player}>{pauseToggle?"=":">"}</button>
    </div>
  )

}

export default Music;

I'm unable to pause the audio, instead it gets played twice when I try to pause. I tried to get help from this Unable to pause audio in Reactjs but it didn't helped

Any other solution for pausing audio file?

Thank You in advance

CodePudding user response:

I believe the music variable should be stateful so it's retained across renders.

const [music] = useState(new Audio(require(`./Alan.mp3`)));

and isPlaying should probably be found by querying the Audio object (music) and/or updated by listening for play/pause state changes.

CodePudding user response:

I'd simplify state to a single boolean: your audio is either playing or not, so there's no need for redundancy here. let isPlaying = false; isn't state, so it's not persistent across renders and doesn't do anything pauseToggle doesn't already achieve.

Since the audio is a side effect to the rendering, I'd make it a ref, then trigger play/pause functions based on when playing changes in a useEffect.

A bit of a bonus, but it's probably worth handling the onended event to set playing to false when the track ends, for starters.

const {useEffect, useRef, useState} = React;

const MusicPlayer = ({url}) => {
  const [playing, setPlaying] = useState(false);
  const audioRef = useRef(new Audio(url));

  useEffect(() => {
    const handler = () => setPlaying(false);
    audioRef.current.addEventListener("ended", handler);
    return () => 
      audioRef.current.removeEventListener("ended", handler)
    ;
  }, [audioRef.current]);

  useEffect(() => {
    audioRef.current[playing ? "play" : "pause"]();
  }, [playing]);

  return (
    <div>
      <button onClick={() => setPlaying(!playing)}>
        {playing ? "=" : ">"}
      </button>
    </div>
  );
};

const url = "https://upload.wikimedia.org/wikipedia/en/a/a9/Webern_-_Sehr_langsam.ogg";
ReactDOM.render(
  <MusicPlayer url={url}/>,
  document.querySelector("#app")
);
button {
  font-size: 2em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="app"></div>

Putting the audio into a hook helps make it reusable and keeps your parent component clean:

const {useEffect, useRef, useState} = React;

const useAudio = url => {
  const [playing, setPlaying] = useState(false);
  const audioRef = useRef(new Audio(url));

  useEffect(() => {
    const handler = () => setPlaying(false);
    audioRef.current.addEventListener("ended", handler);
    return () => 
      audioRef.current.removeEventListener("ended", handler)
    ;
  }, [audioRef.current]);

  useEffect(() => {
    audioRef.current[playing ? "play" : "pause"]();
  }, [playing]);

  return [playing, setPlaying];
};

const MusicPlayer = ({url}) => {
  const [playing, setPlaying] = useAudio(url);

  return (
    <div>
      <button onClick={() => setPlaying(!playing)}>
        {playing ? "=" : ">"}
      </button>
    </div>
  );
};

const url = "https://upload.wikimedia.org/wikipedia/en/a/a9/Webern_-_Sehr_langsam.ogg";
ReactDOM.render(
  <MusicPlayer url={url}/>,
  document.querySelector("#app")
);
button {
  font-size: 2em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="app"></div>

  •  Tags:  
  • Related