Home > Software engineering >  audio play & pause in react
audio play & pause in react

Time:08-25

I'm trying to make a music app, I can start the audio fine, but when it comes to pausing it's not working this is the code :

const handlePlay = (id) => {
    console.log(id);
    audio && audio.pause();
    fetch(`https://spotify23.p.rapidapi.com/tracks/?ids=${id}`, options)
      .then((response) => response.json())
      .then((response) => {
        console.log(response.tracks);
        return response.tracks[0].preview_url;
      })
      .then((response) => {
        setAudio(new Audio(response));
        audio.play();
      })
      .catch((err) => console.error(err));
  };

so I'm calling an API and getting the audio link here to play the audio :

setAudio(new Audio(response));
audio.play(); 

and at the top of the function I have this to check if audio is not null and if it is not so pause, like so:

audio && audio.pause();

but it's not working it's stacking the audio together, and even if I press on another audio it played the first one pressed

this is the react code that triggers handle play for each audio available :

{tracks &&
            tracks.map((track) => (
              <div
                className="w-full h-1/12 p-4 hover:bg-gray-300 hover:bg-opacity-20 hover:text-emerald-500 cursor-pointer  transition duration-150 "
                key={track.data.id}
                onClick={() => handlePlay(track.data.id)}
              >
                <div className="flex items-center ">
                  <svg
                    xmlns="http://www.w3.org/2000/svg"
                    viewBox="0 0 24 24"
                    fill="currentColor"
                    className="w-6 h-6 mr-2"
                  >
                    <path
                      fillRule="evenodd"
                      d="M4.5 5.653c0-1.426 1.529-2.33 2.779-1.643l11.54 6.348c1.295.712 1.295 2.573 0 3.285L7.28 19.991c-1.25.687-2.779-.217-2.779-1.643V5.653z"
                      clipRule="evenodd"
                    />
                  </svg>

                  <h1 className="text-xl ">{track.data.name}</h1>
                </div>
                <div className="text-sm font-thin">
                  by{" "}
                  {track.data.artists.items.map((artist) => (
                    <span key={artist.uri} className="">
                      {artist.profile.name}
                    </span>
                  ))}

CodePudding user response:

The problem is likely here:

setAudio(new Audio(response));
audio.play(); 

The setAudio function is asynchronous, so it will not immediately update the value for the audio state variable. That means that when you immediately invoke audio.play(), it is going to play the previous audio value.

If you want the audio to play automatically once it is loaded, then you can remove the audio.play() invocation in the fetch callback, and then add a useEffect hook to take care of that:

useEffect(() => {
  audio && audio.play();
}, [audio]);
  • Related