音频 play/pause 切换在反应中不起作用

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>

);
}

这个开关有什么问题?当我按下播放按钮时,它会播放音乐,但当我再次按下它时,它会开始另一个音乐会话,就像使用另一个新的 Audio() 方法而不是暂停它一样!

编辑:暂停不起作用,每次开始播放时都会开始新的音频会话

每次组件重新渲染时,setPlaying 调用都会导致重新渲染并初始化 Audio 的新实例,您必须调用 useRef 来持久化 Audio 每个渲染之间的实例:

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;