28

i have a that i want to play a very small mp3 once that is in my public folder in my react app, there are so many different solutions to playing audio but none that are simple for react, i tried react-360 but there was a problem with one of the modules.

i've tried some react audio libraries, but they seem to be for audio players, i dont need a play button and a pause and a volume and all that. just want a simple sound effect

class App extends Component {
  render() {

    var audio = new Audio("../public/sound.mp3")

    return (
      <Container>
            <img src={dwight} onClick={ audio.play() }/>
      </Container>
    );
  }
}

(sound to play when click the image)

Kas Elvirov
  • 7,394
  • 4
  • 40
  • 62
Christopher Ducote
  • 293
  • 1
  • 3
  • 7

8 Answers8

61

Hooks version (React 16.8+):

Minimal version.

Place your music file (mp3) in the public folder.

import React from 'react';

function App() {
  let audio = new Audio("/christmas.mp3")

  const start = () => {
    audio.play()
  }

  return (
    < div >
      <button onClick={start}>Play</button>
    </div >
  );
}

export default App;
Hunter
  • 3,080
  • 20
  • 23
  • 2
    You probably want to wrap the `audio` in `useMemo` or move it to outside of the component to prevent issues when the component re-renders – nrofis Mar 14 '21 at 13:02
  • 22
    Am I missing something or is there no hook in this answer? – DeltaFlyer Mar 25 '21 at 12:49
  • 1
    By “hooks version (React 16.8+)”, I think the OP meant React functional components version rather than class components. There is no hook here but there is a functional component. – ionosphere May 21 '23 at 14:31
11

You can import the audio using import statement and create a Audio object and call the play() method using the instantiated object.

import React from "react";
import audio from './../assets/audios/success.mp3';

class AudioTest extends React.Component{

  playAudio = () => {
    new Audio(audio).play();
  }

  render() {
    return (
        <div>
          <button onClick={this.playAudio}>PLAY AUDIO</button>
        </div>
    );
  }
}

export default AudioTest;
Codemaker2015
  • 12,190
  • 6
  • 97
  • 81
2
  1. Add to your render method<audio id="audio"><source src="slow-spring-board.mp3" type="audio/mp3"></source></audio>
  2. And inside the script document.getElementById('audio').play()
Nagibaba
  • 4,218
  • 1
  • 35
  • 43
1

You need to pass a function thats trigger play:

<Container>
    <img src={dwight} onClick={ () => audio.play() }/>
 </Container>
Artem Mirchenko
  • 2,140
  • 1
  • 9
  • 21
0
<Container>
    <img src={dwight} onClick={audio.play}/>
</Container>

By passing audio.play as the onClick handler, rather than audio.play(), you're passing the play function itself. audio.play() will instead invoke the function - if it also returned a function for some reason, then that function would be invoked on click.

Ben R.
  • 1,965
  • 1
  • 13
  • 23
0

so i moved the sound and picture files INSIDE of the src folder, into assets, THEN changed the onClick function to a combo that finally worked, it looks like a double invocation did the trick


class App extends Component {
  render() {
    return (
      <Container>
        <img src={dwight} alt="ds" onClick={() => audio.play()} />
        <h1> PRESS ME</h1>
      </Container>
    );
  }
}

export default App;
Christopher Ducote
  • 293
  • 1
  • 3
  • 7
0
import { Fragment } from 'react';
export default function PlaySound(props) {
    var savingCurrencySound = props.soundFile ?? 'https://example.com/audio/sound.mp3';
    var playCurrencySound = () => {     
        var audio = new Audio(savingCurrencySound);
        audio.play();
    }
    return (
        <Fragment>
            <img src={dwight} onClick={ () => playCurrencySound() }/>
        </Fragment>
    );
}
  • This solution was provided before, can you add more details to your answer so that if can differentiate of the others? Otherwise it looks like a copied answer. – Cristik Feb 09 '22 at 18:33
  • @Cristik - the minor difference is to pass the relative url of sound file instead of file path of audio file. – Gaurav Trivedi Feb 11 '22 at 04:38
  • Thanks, can you expand this on the answer? This will also increase its quality, as currently it's a code-only answer, a code that seems copy+pasted from another answer. – Cristik Feb 18 '22 at 05:43
  • Already in response – Gaurav Trivedi Feb 20 '22 at 16:32
0

According to this answer

here's the following worked code :

import React, { useState, useEffect } from "react";

const useAudio = url => {
  const [audio] = useState(new Audio(url));
  const [playing, setPlaying] = useState(false);

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

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

  useEffect(() => {
    audio.addEventListener('ended', () => setPlaying(false));
    return () => {
      audio.removeEventListener('ended', () => setPlaying(false));
    };
  }, []);

  return [playing, toggle];
};

const Player = ({ url = 'https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3' }) => {
  const [playing, toggle] = useAudio(url);

  return (
    <div>
      <button onClick={toggle}>{playing ? "Pause" : "Play"}</button>
    </div>
  );
};

export default Player;

or you can use this playground here

acul
  • 53
  • 7
  • The type of `toggle` in `Player` component is oddly `boolean | (() => void)` in Typescript. So `onClick` on `button` is raising a compile-time error saying "Type 'boolean | (() => void)' is not assignable to type 'MouseEventHandler'.". – Eray Erdin Nov 21 '22 at 08:47