使用HTMLAudioElement

时间:2019-04-09 01:59:27

标签: javascript reactjs react-hooks

我编写了一个名为useAudio的自定义React挂钩,以在应用程序的背景中播放声音。

为什么useEffect会抛出Uncaught (in promise) DOMException

我已将问题缩小到自定义挂钩中的第二个useEffect。当指示音频是否为playing的布尔值发生变化时,就会产生这种效果。

所有React说的是Uncaught Error: The error you provided does not contain a stack trace.

我还尝试将audio修改为常规常量,而不是通过useState钩子进行声明,但这并不能解决问题。

import React, { useState, useEffect } from 'react'
import styled from 'styled-components'

const useAudio = (url: string) => {
  if (typeof Audio !== 'undefined') {
    const [audio] = useState(new Audio(url))
    const [playing, setPlaying] = useState(false)

    const toggle = () => setPlaying(!playing)

    useEffect(() => {
      audio.loop = true
      audio.autoplay = true
    })

    useEffect(() => {
      playing ? audio.play() : audio.pause()
      return () => {
        audio.pause()
      }
    }, [playing])

    return [playing, toggle]
  }
}

const AudioPlayer: React.FC<{ url: string }> = ({ url }) => {
  if (typeof Audio !== 'undefined') {
    const [playing, toggle] = useAudio(url)

    return (
      <AudioContainer>
        {typeof playing !== 'undefined' && (
          <Button onClick={() => toggle()}>
            {playing ? 'Stop music' : 'Play music'}
          </Button>
        )}
      </AudioContainer>
    )
  }
  return null
}

export default AudioPlayer

它正在live app中工作。

不是在这个孤立的Codesandbox中工作。

我希望音频在安装组件时开始,并且不会引发DOMException。

1 个答案:

答案 0 :(得分:1)

关于应用程序,您有一些含糊之处,包括在条件条件下使用钩子并在状态下存储audio对象(尝试使用useRef,这是它的唯一目的)。但是问题的核心似乎是您要馈送到url的{​​{1}}是Audio。我猜想CodeSandbox环境没有适合undefined文件的加载程序。请尝试一些直接URL。

沙箱:https://codesandbox.io/s/l7775jm2rm