Play audio with React

Viewed 17488

Whatever I do, I get an error message while trying to playing a sound:

Uncaught (in promise) DOMException.

After searching on Google I found that it should appear if I autoplayed the audio before any action on the page from the user but it's not the case for me. I even did this:

componentDidMount() {
  let audio = new Audio('sounds/beep.wav');
  audio.load();
  audio.muted = true;
  document.addEventListener('click', () => {
    audio.muted = false;
    audio.play();
  });
}

But the message still appears and the sound doesn't play. What should I do?

3 Answers

The audio is an HTMLMediaElement, and calling play() returns a Promise, so needs to be handled. Depending on the size of the file, it's usually ready to go, but if it is not loaded (e.g pending promise), it will throw the "AbortError" DOMException.

You can check to see if its loaded first, then catch the error to turn off the message. For example:

componentDidMount() {
      this.audio = new Audio('sounds/beep.wav')
      this.audio.load()
      this.playAudio()
}

playAudio() {
    const audioPromise = this.audio.play()
    if (audioPromise !== undefined) {
      audioPromise
        .then(_ => {
          // autoplay started
        })
        .catch(err => {
          // catch dom exception
          console.info(err)
        })
    }
}

Another pattern that has worked well without showing that error is creating the component as an HTML audio element with the autoPlay attribute and then rendering it as a component where needed. For example:


const Sound = ( { soundFileName, ...rest } ) => (
  <audio autoPlay src={`sounds/${soundFileName}`} {...rest} />
)

const ComponentToAutoPlaySoundIn = () => (
   <>
     ...
     <Sound soundFileName="beep.wav" />
     ...
   </>
)

Simple error tone

If you want something as simple as playing a simple error tone (for non-visual feedback in a barcode scanner environment, for instance), and don't want to install dependencies, etc. - it can be pretty simple. Just link to your audio file:

import ErrorAudio from './error.mp3'

And in the code, reference it, and play it:

var AudioPlay = new Audio (ErrorAudio);
AudioPlay.play();

Only discovered this after messing around with more complicated options.

Related