In my return statement of my react code I have:
<audio id="myAudio"> <source src="49.mp3" type="audio/mpeg"></source> </audio>
This creates a HTML object for the audio. I have a file called 49.mp3 in the same directory as my code. Then I have an event listener that plays that sound when a key is pressed:
const handleKeyDown = (event) => { const { key } = event; if (event.repeat) { return; } setTimeout(() => { document.getElementById("myAudio").play(); }, 500); }
When I press my key, I know this function gets called but no audio plays. I don’t get any error messages, but I don’t hear anything. I also tried playing the audio in other ways (all this code is on the keydown listener):
//Try 1 var x = document.getElementById("myAudio"); x.play(); //Try 2 var audio = new Audio("49.mp3"); audio.play(); //Try 3 import { Howl, Howler } from "howler"; var sound = new Howl({ src: ['49.mp3'] }); sound.play();
Sadly none of these methods work. I don’t hear any sounds. Please let me know what the problem is, and how I could fix it.
Advertisement
Answer
I Think this is a great example of a place you would use a react Dom Ref! Here is a quick Proof of Concept I threw together that plays audio whenever a key is pressed. I’ll go through each part.
import logo from './logo.svg'; import './App.css'; import React, {useEffect} from "react" import Mp3 from "./shared/sound.mp3" function App() { const audioRef = React.createRef(); const handleKeydown = (event) => { if (event.repeat) { return; } audioRef.current.play(); } useEffect(() => { document.addEventListener("keydown", (event) => handleKeydown(event)); //cleanup return () => { document.removeEventListener("keydown"); } }) return ( <div className="App"> <audio src={Mp3} ref={audioRef}/> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <p> Edit <code>src/App.js</code> and save to reload. </p> <a className="App-link" href="https://reactjs.org" target="_blank" rel="noopener noreferrer" > Learn React </a> </header> </div> ); } export default App;
Lets go over the solution
First we import our asset file (in this case an mp3) at the top of our file as if it were a component. This gives us a variable that we can access the file from later
import Mp3 from "./shared/sound.mp3"
Next we create a Ref which we will use to access the Audio Dom node later.
const audioRef = React.createRef();
If you are unfamiliar with React Refs I would suggest reading a bit more on them from the official docs here
Next we define our keyDownHandler just like you did
const handleKeydown = (event) => { if (event.repeat) { return; } audioRef.current.play(); }
In our effectHook we set up our eventListener and remove it as part of cleanup so the eventListener doesn’t hang around when the component is removed from the page.
useEffect(() => { document.addEventListener("keydown", (event) => handleKeydown(event)); //cleanup return () => { document.removeEventListener("keydown"); } })
The outer part of the callback will behave as componentDidMount()
and the returned function will behave as componentDidUnmount()
you can feel free to use those if you prefer class Components.
Lastly, we add the audio tag and point the src to the mp3 file we imported at the top of the file, and set its ref to the audioRef we created earlier
<audio src={Mp3} ref={audioRef}/>
You should be able to modify this solution in any way you see fit. Let me know if you have any farther questions, and make sure to close your question if this answer clears it up.
EDIT: To make the sound restart on each button press you can update the key down handler to the following:
const handleKeydown = (event) => { audioRef.current.pause(); audioRef.current.currentTime = 0; audioRef.current.play(); }