2
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. IInstead 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 help.

Any other solution for pausing audio file?

ggorlen
  • 44,755
  • 7
  • 76
  • 106
Shubham Singhvi
  • 304
  • 1
  • 10

2 Answers2

2

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.

Dave
  • 7,552
  • 4
  • 22
  • 26
0

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.

In fact, audio elements have a .paused property that makes the separate state boolean redundant, but for React rendering/lifecycle purposes the extra boolean is handy.

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.createRoot(document.querySelector("#app"))
  .render(<MusicPlayer url={url}/>);
button {
  font-size: 2em;
}
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.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.createRoot(document.querySelector("#app"))
  .render(<MusicPlayer url={url} />);
button {
  font-size: 2em;
}
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="app"></div>
ggorlen
  • 44,755
  • 7
  • 76
  • 106