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]);