Parham Moieni
Parham Moieni

Reputation: 81

audio play/pause toggle not working in react

function MusicCard() {
const [playing, setPlaying] = useState(false);

const url = "http://localhost:4000/musics/myMusic.mp3";
const audio = new Audio(url);

const play = () => {
    setPlaying(true);
    audio.play();
};

const pause = () => {
    setPlaying(false);
    audio.pause();
};

return (
    <div className="music-card">
        <div className="music-card_image-con">
            <button style={{
                backgroundImage: `url(${process.env.PUBLIC_URL}music-image.jpg)`
            }} onClick={playing ? pause : play}>{ playing ? <FaPause /> : <FaPlay /> }</button>
        </div>
        <div className="music-card_info-con">
            <div className="music-card_info-name">
                <h3>music name</h3>
                <p> - </p>
                <p>Singer</p>
            </div>
            <div className="music-card_info-seekbar">
                <input type="range" style={{
                    width: "100%"
                }} />
            </div>
        </div>
        <button className="music-card_actions-btn"><FaEllipsisV /></button>
    </div>

);
}

what is the problem with this toggle? when I press the play button it plays the music but when I pres it again it starts another session of the music like using another new Audio() method instead of pausing it!

Edit: the pause doesn't work and play starts new session of Audio every time starting to play

Upvotes: 1

Views: 3597

Answers (1)

Steven Than
Steven Than

Reputation: 454

The setPlaying call causes re-rendering and initializes a new instance of Audio every time the component re-renders, you'll have to call useRef to persist the Audio instance between each render:

import { useState, useRef } from "react";

function MusicCard() {
  const [playing, setPlaying] = useState(false);

  const url = "http://localhost:4000/musics/myMusic.mp3";

  const audioRef = useRef(new Audio(url));

  const play = () => {
    setPlaying(true);
    audioRef.current.play();
  };

  const pause = () => {
    setPlaying(false);
    audioRef.current.pause();
  };

  return (
    <div className="music-card">
      <div className="music-card_image-con">
        <button
          style={{
            backgroundImage: `url(${process.env.PUBLIC_URL}music-image.jpg)`,
          }}
          onClick={playing ? pause : play}
        >
          {playing ? <FaPause /> : <FaPlay />}
        </button>
      </div>
      <div className="music-card_info-con">
        <div className="music-card_info-name">
          <h3>music name</h3>
          <p> - </p>
          <p>Singer</p>
        </div>
        <div className="music-card_info-seekbar">
          <input
            type="range"
            style={{
              width: "100%",
            }}
          />
        </div>
      </div>
      <button className="music-card_actions-btn">
        <FaEllipsisV />
      </button>
    </div>
  );
}

export default MusicCard;

Upvotes: 2

Related Questions