Drum Machine not playing on first press

So I was doing the Front End Developing Libraries Drum Machine project, and just when I thought that I have finally done it, I couldn’t pass the tests.

As it seems, my drum pad buttons never work for the first press, only subsequent presses, and every time I press another button the same thing happens, the first press never plays. Upon inspection, I found the error of “Uncaught (in promise) DOMException: The play() request was interrupted by a call to pause().” while I have not used any single pause() in my entire code.

const play = (key, sound) => {
const audio = document.getElementById(key);
audio.currentTime = 0;
audio.play();
setBankName(sound);
};

Weirdly enough, in this section where I have the play function and the setBankName(sound) for updating the string that appears on the screen every time a button is pressed. When I remove the setBankName(sound) function, it works on the first press now, the audio plays, but I still fail the test because the User Story #7 is now failed since the string no longer updates with every press. If I don’t remove it, other ones fail. How does this setBankName(sound) function affects my audio.play()? And how can I solve it? Thank you in advance to whoever is willing to reply to me.

Your code so far

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36

Challenge: Build a Drum Machine

Link to the challenge:

It could be interesting to have a volume controller for each key

I didn’t really try to figure out what is going on but if you move the setBankName call up to before the getElementById selector it also works.

const play = (key, sound) => {
setBankName(sound)
const audio = document.getElementById(key)
audio.currentTime = 0
audio.play()
};
I changed it to this and yet it still shows tests failed to me :frowning:

I wasn’t talking about the test, I never even ran them. I was just talking about the bug you were seeing with the keyboard not triggering the sound on the first keypress. But I see now it happens with the clicks as well. I would have to look more at the code to see what is going on, which probably won’t happen right now. I don’t have an answer right now, it might be how the handler is passed down, or where it is being registered.

Just as an aside. The error you are seeing in the console shouldn’t affect the tests. It has been an issue for a very long time now and projects that pass all the tests can (most likely will) still throw that error. It has to do with the test calling pause and how play returns a promise, you can read more about it in the link the error provides. My old project throws that error as well but it still passes all the tests.

Hi, you’re getting this issue because you of setBankName in your play function.
Remove it and it will work.

You have to understand how setState works and how it causes a re-render which stops your audio from effectively playing.

But now you run in to the issue of updating the state without affecting the play you can probably figure out how do it though…

How I figured it out was seeing how when you use the keyboard it works fine but with mouse clicks it didn’t the difference was how you were using useEffect to again rerender

Hi, you’re getting this issue because you of setBankName in your play function.
Remove it and it will work.

I tried making another handlePress function that calls play() function and the setBankName() in it when pressed, instead of placing the setBankName() inside the play(), but it still doesn’t work the way I intended it to. I feel pretty stuck on how I should do this now.

There is different ways to solve this

You could do your state updates first with the onclick which would then trigger a useEffect which can then have your play function as one option

1 Like

I have never used useEffect in such a way before, I don’t know how should I write it. I tried writing

useEffect(() => { play(keyTrigger, id) }, bankName)

thinking that it will run play() if bankName changes, but still, it doesn’t work. Can you show me a worked example of how you would approach this problem?

I was able to get it to work doing something like this with a new state that contains the id and trigger of the button clicked:

  const [player,setPlayer] = React.useState({id:"",keyTrigger:""})

    React.useEffect(()=>{
      if (player.keyTrigger){
            play(player.keyTrigger,player.id)
        console.log("test")
      }
   },[player])

This should help you out, all you have to do now is make your onClick trigger setPlayer with the correct info. There is a lot of rerender though and code isn’t optimized because it would be too much effort for me refactoring the code.

1 Like

Thank you a lot! I finally got it to work thanks to you! But then… It still says 5/8 tests passed for some reason.

  1. When I click on a .drum-pad element, the audio clip contained in its child <audio> element should be triggered.

I am sure my clickable buttons have the className="drum-pad", and when it is clicked, it plays the audio (even on the first click now, thanks to you!). So I don’t get why this test still throws a fail to me.

  1. When I press the trigger key associated with each .drum-pad, the audio clip contained in its child <audio> element should be triggered (e.g. pressing the Q key should trigger the drum pad which contains the string “Q”, pressing the W key should trigger the drum pad which contains the string “W”, etc.).

This is by far the most confusing and annoying fail test I got since the keyboard part of the soundboards was THE only part working exceptionally well, fully functional with 0 issues at all upon pressing. So I have no idea why this one still gives me fail.

  1. When a .drum-pad is triggered, a string describing the associated audio clip is displayed as the inner text of the #display element (each string must be unique)

THIS is the test I was struggling with, that drove me to create this thread in the first place. I thought that as long as I can make the audio play at first click, while preserving the setstate() function of setBankName() in my code, this would throw me a pass. It didn’t, it still gave me a fail for some reason. I even moved the id="display" declaration from the wrapping <div> element into the <h3> element enclosing the {bankName}, making it <h3 id="display">{bankName}</h3> in my render return but it still doesn’t work.

Perhaps I got too drained trying to work this project out for an extended period of time, I already feel blessed having the code work the way it was intended now, being the way it is. I dread the idea of tinkering more and refactoring more of this inexperienced mess I made just to create another same page that somehow throws a pass to all that 3 remaining tests. I think I’m going to submit this work as it is.

I referenced way too many videos, other people’s works, and forum threads on not only this drum machine, but all of my other Front End Development Libraries projects too. I feel guilty as I did not put in most of the effort myself, by my own original ideas. So I might come back in the near future to redo all of these projects from scratch. Again, thanks for the help, I couldn’t have done this without your generous help and guidance, Jimbalin! I owe you a big one, and I’ll repay it in the form of giving similar help to other members of the community in the future.

I think what’s happening is that because your buttons get re rendered it doesn’t pass the tests. For example, if you inspect the element of the button and click it it is recreated since your button is re rendered due to state updates. You could remedy that by holding your buttons in state so it doesn’t change.

I’m going to give you some general advice that I think is useful:
Don’t code everything at once and then test it out, work on one item at a time. What this means is that don’t make all your buttons; start with one because once you get that one button working, the others can be done the same way.

Following the advice above my personal preference is to work on the JS first and ignore CSS til the end. The reason is because you want to make sure it’s working before first before styling. Otherwise you’ll go back and forth because the JS may require different elements in different places.

I recommend also using a different tool to store your code since a long file is harder to read than one where the components are broken down into separate files

Lastly I don’t think you need to go back to do these projects. It’s better to come up with new ones on your own so it’s unique this way you won’t refer to other people’s code/solutions.

1 Like