Drum Machine Project: my app logic seems to be working correctly, but it is not passing tests 5-8

Tell us what’s happening:

Hello,

So far I have only been setting up React logic for my app and it seems to be working correctly at the moment. The display gets updated and correct audio gets played when I either click on a corresponding keyboard key and whenever I click it through manually clicking on a corresponding button with mouseclick.

However, for some reason it is not passing the tests 5-8 and I’m not sure why.

Here is my pen.

Basically I set up an event listener for keyboard event and conditions for updating the state if a right key is pressed:

componentDidMount() {
    const setKeyDown = (event) => { this.setState({ keyPressed: event.key.toUpperCase() }) }
    const setKeyUp = (event) => { this.setState({ keyPressed: "" }) }
    
    document.addEventListener('keydown', setKeyDown)
    document.addEventListener('keyup', setKeyUp)
  }
  
  componentWillUnmount() {
    const setKeyUp = (event) => { this.setState({ keyPressed: "" }) }
    document.addEventListener('keyup', setKeyUp)
  }
  
  componentDidUpdate() {
    if (this.state.keyList.includes(this.state.keyPressed) && this.state.power) {
      let buttonClicked = document.getElementById(this.state.keyPressed+"-button")
      buttonClicked.click()
    }
  }

The drumpad element looks like this (it is getting triggered by buttonClicked.click() in case of keyboard event or onClick in case of mouse click):

function Drumpad(props) {
  return (
    <div className="drum-pad" id={props.audioBank.padID}>
      <button 
        type="button"
        id={props.keyValue+"-button"}
        name={props.keyValue} 
        value={props.audioBank.value} 
        tabIndex="0"
        onClick={props.handleClick}
        disabled={!props.power}>
        {props.keyValue}
      </button>

      <audio 
        className="clip" 
        id={props.keyValue} 
        src={props.audioBank.audioSource} />
    </div>
  )
}

Please let me know what I’m doing incorrectly here.

Cheers,
Konstantin

Your browser information:

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

Challenge: Build a Drum Machine

Link to the challenge:

Hello there,

The issue the tests are having is they are trying to click on the elements with className="drum-pad". You have elements with this class, however, they are unclickable (technical term).

Hope this clarifies.

1 Like

Hello,

I modified my code to include <audio> inside the button element and got rid of the div for that component, it is still working same way, which seems to be correct but still not passing some tests (says 7/8 tests were passed but when I look into detailed description I see that both tests #6 and #7 are failed). I’m still confused why is it happening.

Basically the main change I applied to my code is in the Drumpad component:

function Drumpad(props) {
  return (
    <button 
      type="button"
      className="drum-pad"
      id={props.keyValue+"-button"}
      name={props.keyValue} 
      value={props.audioBank.value}
      onClick={props.handleClick}
      disabled={!props.power}>
      {props.keyValue}
      <Audio keyValue={props.keyValue} audioSource={props.audioBank.audioSource} />
    </button>
  )
}

And moved <audio> into a separate stateless functional component:

function Audio(props) {
  return (
    <audio 
      className="clip" 
      id={props.keyValue}
      src={props.audioSource} />
  )
}

Here is my modified pen.

What are you wanting to do here:

var audio = document.getElementById(name)
audio.volume = this.state.volume / 100.0
audio.paused ? audio.play() : audio.currentTime = 0 //This line is incorrect syntax

In the first line I’m getting the audio element by its ID, then setting up it’s volume based on the volume stored in the state and then on the third line I’m checking whether audio element was paused, then play, if not I stop it and then play.

Basically I’ve set the last line to allow a user to click on the same button multiple time as on a regular drum machine. Before I did it with just audio.play() and the drum machine wouldn’t play a sound when I click multiple times in a row on the same pad. It would wait until the first sound finishes playing and only then play it again.

I tried to modify this line just on audio.play() but it is still failing those tests

Right, but the syntax error on the third line is still an issue. You cannot make an assignment expression within a ternary operation. That is where if...else are still valid.

Also, I am not understanding that logic:

  • If audio is paused, then play audio, otherwise, reset to 0.

When is the audio ever paused? You do not have a pause button…

So basically if I set it up as just audio.play() instead of this ternary and pressed W key multiple times and audio file duration is, for example, 2 seconds, it would wait until the sound that is triggered by the first press is finished playing and would only allow me to trigger this sound again after 2 seconds.

With this ternary I press W key multiple times within those 2 seconds audio file duration it will pause the previously triggered sound and trigger it again with each new pressing on the key.

I understand why you want it. The issue is:

The logic always evaluates to false. So, you might as well have:

audio.currentTime = 0;
audio.play();

I made this modification, but for some reason my application still fails the same tests

Currently, the issue is that the script is erroring out, and you can see this in the browser console:
Uncaught (in promise) DOMException: The play() request was interrupted by a call to pause(). https://goo.gl/LdLk22

The link provided by Google is quite informative. I suggest you start there.

1 Like

Thank you very much for your help :slight_smile: