无法在 ReactJs 中使用 setState 方法播放不同的歌曲

Unable to play a different song using setState method in ReactJs

// TuneContainer.js
import React, {useState} from 'react'
import './TuneContainer.css'

function TuneContainer(props) {
    const[isPlaying, setIsPlaying] = useState(false)
    const[isPaused, setIsPaused] = useState(true)

    const audio = document.querySelector('audio')

    const audioControls = () => {
        if(isPaused) {
                console.log(isPlaying)
                console.log(isPaused)
            setIsPlaying(!isPlaying)
            setIsPaused(!isPaused)
                console.log(isPlaying)
                console.log(isPaused)
            audio.play()
        } else {
            setIsPlaying(!isPlaying)
            setIsPaused(!isPaused)
            audio.pause()
        }
    }

    return (
        <>
            <div className="tune-container">
                <div className="info-class">
                    <img src={props.imgsrc} className="tune-img" alt={props.imgalt} onClick={audioControls}></img>
                    <audio src={props.audiosrc} id="tune" loop hidden></audio>
                </div>
            </div>
                    
        </>
    )
}

export default TuneContainer

以上是包含图片的容器的代码,点击它会无限循环播放歌曲,直到点击图片再次暂停。下面给出的是调用 TuneContainer 并向其传递道具的主页。

// HomePage.js
import React from 'react'
import NavigationBar from './NavigationBar'
import TuneContainer from './TuneContainer'
import Bird from '../images/Bird.svg'
import BirdWhistling from '../audios/Bird-whistling.mp3'
import Leaves from '../images/Leaves.svg'
import LeavesRustling from '../audios/Rustling-leaves.mp3'

function HomePage() {
    return (
        <>
            <NavigationBar />
            <div className="container">
                <TuneContainer audiosrc={BirdWhistling} imgsrc={Bird} imgalt="Bird by Ana María Lora Macias from the Noun Project"/>
                <TuneContainer audiosrc={LeavesRustling} imgsrc={Leaves} imgalt="leaves by KP Arts from the Noun Project"/>
            </div>
        </>
    )
}

export default HomePage

所以在这里,当我点击小鸟图像时,我听到了鸣叫声,因为这些是通过的道具。第二个 TuneContainer 具有完全不同的图像和音频。但是,当点击树叶图像时,它仍然播放叽叽喳喳的声音。所以我相信音频源没有正确更新。有人可以强调我哪里做错了吗?

P.S: 在有人问之前,我已经正确检查了所有的路径和文件名,没有,两个音频文件中的歌曲不同他们。


虽然我知道 SO 强烈建议一个问题问一个问题 post,但我将在此处添加我的第二个问题,因为它高度相关并且不需要额外的代码。

问: 当我检查控制台时,打印的值(由于 console.log 语句)是 false, true, false, true。我相信它应该打印 false, true, true, false,因为我在 setState 函数之前和之后打印一次。为什么会有这样的行为?

因为 document.querySelector('audio') 总是 return 第一个 html 音频元素,在您的例子中是鸟鸣声。

您可以为每个 TuneContainer 使用唯一的 (id) 标识符。在您的音频标签上使用该 ID 并查询 select 该 ID,这将指向正确的音频元素。

另一种方法是使用 useRef 获取音频元素。

// TuneContainer.js
...
const audioRef = React.useRef(null);
/* const audio = document.querySelector('audio') */

const audioControls = () => {
  if(isPaused) {
    console.log(isPlaying)
    console.log(isPaused)
    setIsPlaying(!isPlaying)
    setIsPaused(!isPaused)
    console.log(isPlaying)
    console.log(isPaused)
    // audio.play()
    audioRef.current.play();
  } else {
      setIsPlaying(!isPlaying)
      setIsPaused(!isPaused)
      // audio.pause()
      audioRef.current.pause();
    }
};

...
...
return (
  ...
  ...
    <audio ref={audioRef} src={props.audiosrc} id="tune" loop hidden></audio>
  ...
);