I recently ran into this as well. The problem with using Howler directly in JavaScript is that you'll need to manage the Howl instance manually. When your component dismounts, you'll need to stop any playing sounds.
React Howler exists which solves this:
import React, { useState } from 'react'
import ReactHowler from 'react-howler'
export default function PlayPause() {
const { play, setPlay } = useState(false)
return (
<div>
<ReactHowler src='./sound.mp3' playing={play} />
<button onClick={() => setPlay(!play)}>
{ play ? 'Pause' : 'Play' }
</button>
</div>
)
}
I have to admit, though, that React Howler didn't solve my use case because it doesn't actually implement all of howler's features, particularly audio sprites.
I ended up writing my own library, Rehowl. It separates out the loading of the file from the playing of sounds like so:
import React, { useState } from 'react'
import { Play, useHowl } from 'rehowl'
export default function PlayPause() {
const { play, setPlay } = useState(false)
const { howl } = useHowl({ src: './sound.mp3' })
return (
<div>
<Play howl={howl} pause={!play} />
<button onClick={() => setPlay(!play)}>
{ play ? 'Pause' : 'Play' }
</button>
</div>
)
}
The useAudioPlayer library linked in another answer seems like another solid alternative to react-howler.
In any case, I'd say that using Howler directly in a React project will cause headaches as managing playing sounds while dealing with the component lifecycle is hard.