React.js - useEffect() 钩子中的 removeEvent()

时间:2021-06-14 09:07:22

标签: javascript html reactjs jsx use-effect

我正在尝试让 HTML5 音频元素在页面加载时自动播放。我知道 Chrome 默认不允许自动播放,除非有什么触发它。所以我在 useEffect() 钩子中创建了几个事件侦听器:

const Audio = () => {
  const audioPlayer = document.getElementById('myAudio')
  const playAudio = () => audioPlayer.play()
  useEffect(() => {
    window.addEventListener('scroll', playAudio)
    window.addEventListener('mousemove', playAudio)
    return () => {
      window.removeEventListener('scroll', playAudio)
      window.removeEventListener('mousemove', playAudio)
    }
  }, [])
  return (
    <audio
      id="myAudio"
      src={ audioAssetHere }
    />
  )
}

这确实有效,但每次光标移动时它都会继续播放。我只想播放一次。我也在控制台中收到此错误:

DOMException: play() failed because the user didn't interact with the document first

但每次光标移动时音频仍然有效。

我还尝试使用 useRef 并将其分配给音频标签 ref={audioRef},然后在 useEffect 挂钩中使用它:

const audioRef = useRef()
const playAudio = () => audioRef.current.play()
useEffect(() => {
    window.addEventListener('scroll', playAudio)
    window.addEventListener('mousemove', playAudio)
    return () => {
      window.removeEventListener('scroll', playAudio)
      window.removeEventListener('mousemove', playAudio)
    }
  }, [])

这给出了错误:

TypeError: audioRef.current.play is not a function

简而言之,我想要的是每次页面加载时播放的音频。而且我只想播放一次。

任何帮助将不胜感激。谢谢

1 个答案:

答案 0 :(得分:2)

您正在尝试在每个 mousemove/scroll 事件上播放音频,而不是您只需要在第一个 mousemove/scroll 事件上播放一次:

const Audio = () => {
  const audioRef = React.useRef();

  useEffect(() => {
    const playAudio = () => {
      audioRef.current.play();
      removeListeners()
    }

    window.addEventListener('scroll', playAudio)
    window.addEventListener('mousemove', playAudio)
    
    const removeListeners = () => {
      window.removeEventListener('scroll', playAudio)
      window.removeEventListener('mousemove', playAudio)
    }
    
    return () => {
      removeListeners()
    }
  }, [])
  
  return (
    <audio
      src={ audioAssetHere }
      ref={ audioRef }
    />
  )
}