how to use howler.js in react?
Asked Answered
R

4

6

Why is it that when I click play, I can play the sound and when I click play, there is no sound??

import React, { Component } from "react";
import { Howl, Howler } from 'howler';

class App extends Component {
  SoundPlay() {
    const Sounds = new Howl({
      src: ["sound.mp3"]
    })
    Sounds.play()
    console.log("sound")
  }
  render() {
    return (
      <div className="App">
        <button onClick={this.SoundPlay}>play</button>
      </div>
    );
  }
}

export default App;
Riyadh answered 26/2, 2019 at 13:23 Comment(2)
Pretty sure it is a path issue. Look at the console and see the url where the browser tries to find the file. (See working codesandbox, the .mp3 file is in the public folder)Sadi
Thanks, I also put the sound. Mp3 file in the public directory. Change it to src :[" /sound.mp3 "] and it will play.Xanthochroism
H
8

I recently published react-use-audio-player which is a react hooks abstraction of howlerjs. You can use it like so:

import { useAudioPlayer } from "react-use-audio-player"

function MyComponent() {
    const { play, pause, stop, playing } = useAudioPlayer()

    const handlePlayPause = () => {
        if (playing) {
            pause()
        } else {
            play()
        }
    }

    return (
        <div className="audioControls">
            <button onClick={handlePlayPause}>
                {playing ? "pause" : "play"}
            </button>
            <button onClick={stop}>stop</button>
        </div>
    )
}
Haberman answered 11/11, 2019 at 0:1 Comment(0)
N
5

Change your code to the following (using / in front of the file name) and make sure your file is in your app's public folder.

const Sounds = new Howl({
    src: ["/sound.mp3"]
})
Nuggar answered 3/10, 2019 at 10:33 Comment(0)
R
4

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.

Raman answered 15/11, 2019 at 2:44 Comment(2)
Did you find React library with audio sprites ?Torray
@ZhivkoZhelev rehowl is a react library that supports audio sprites, see docs for example: tedmor.in/rehowl/?path=/docs/components-play--basic-spriteRaman
A
1

The sound file needs to be imported to the component, just like React and Howler.

import React, { Component } from "react";
import { Howl, Howler } from 'howler';
import newSound from './sound.mp3';

class App extends Component {
  constructor() {
    super()
    this.state = { 
      sound: new Howl({
          src: [newSound]
      })
    }
  }

  render() {
    return (
      <div className="App">
        <button onClick={this.state.sound.play()}>play</button>
      </div>
    );
  }
}

export default App;


You might be able to store the sound in state, if you build a constructor, that way you aren't instantiating a new Howl every time you click play. Something like this.

import React, { Component } from "react";
import { Howl, Howler } from 'howler';
import newSound from './sound.mp3';

class App extends Component {
  SoundPlay() {
    const Sounds = new Howl({
      src: [newSound]
    })
    Sounds.play()
    console.log("sound")
  }
  render() {
    return (
      <div className="App">
        <button onClick={this.SoundPlay}>play</button>
      </div>
    );
  }
}

export default App;

This might throw an error though, with Chrome's AudioContext rules. But I would be interested in seeing if it works!

Annulus answered 5/3, 2021 at 20:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.