React 18 - Drum Machine Test Fail w/ TypeError

Hello everyone,

I created a Drum Machine with dynamic components for each button, and it works when clicked or when the related key on the keyboard is pressed. However, my test fails with the following error:

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

TypeError: n.apply is not a function (https://esm.sh/v135/react-dom@18.3.1/es2022/react-dom.mjs:9)

It seems like the button click event is not properly working in the test. Could you please help me understand what might be wrong? Do I need to use a different approach, or is this possibly a bug?

const DrumButton = ({id, name, srcEnd, onActive }) =>{
const audioRef = useRef(null); 
const [isActive, setIsActive] = useState(false);

 const playSound = () => {
   onActive(name);
    if (audioRef.current) {
      audioRef.current.currentTime = 0;
      audioRef.current.play();
    }
  }

  const handleKeyDown = (event) => {
    const key = event.key;
    if (key === id || key === id.toLowerCase()) {
      setIsActive(true);
      playSound();
      onActive(name); 
    }
  };

  const handleKeyUp = () => {
    setIsActive(false);
  };

  useEffect(() => {
    window.addEventListener("keydown", handleKeyDown);
    window.addEventListener("keyup", handleKeyUp);

    return () => {
      window.removeEventListener("keydown", handleKeyDown);
      window.removeEventListener("keyup", handleKeyUp);
    };
  }, []);
  return(
    <>
      <button onClick={playSound} className={`drum-pad btn ${isActive ? 'active' : ''}`} id={`${id}-button`}>{id}
        <audio 
        id={id}
        className='clip'
        ref={audioRef} 
        src={`https://s3.amazonaws.com/freecodecamp/drums/${srcEnd}.mp3`}
        /></button>
  </>)
}

const DrumMachine = () =>{
const [displayedName, setDisplayedName] = useState("");
  
const handleActiveBtn = (buttonName) =>{
   setDisplayedName(buttonName);
}
return(
   <div className='main-container' id={'drum-machine'}>
    <div className={'display'} id={'display'}>{displayedName}</div>
    <div className='btn-container'>
    {drumAudioElements.map(({ id, name, srcEnd }) => (
        <DrumButton key={`key-${id}`} id={id} name={name} srcEnd={srcEnd} onActive={handleActiveBtn}/>
      ))}
      </div>
    </div>
  )
}

  const drumAudioElements = [
    { id: 'Q', name: 'Heater 1', srcEnd: 'Heater-1' },
    { id: 'W', name: 'Heater 2', srcEnd: 'Heater-2' },
    { id: 'E', name: 'Heater 3', srcEnd: 'Heater-3' },
    { id: 'A', name: 'Heater 4', srcEnd: 'Heater-4_1' },
    { id: 'S', name: 'Clap', srcEnd: 'Heater-6' },
    { id: 'D', name: 'Open HH', srcEnd: 'Dsc_Oh' },
    { id: 'Z', name: 'Kick n\' Hat', srcEnd: 'Kick_n_Hat' },
    { id: 'X', name: 'Kick', srcEnd: 'RP4_KICK_1' },
    { id: 'C', name: 'Closed HH', srcEnd: 'Cev_H2' }
  ]

Live preview and full code codePen.

Edit:
Also, other tests are failing with the same error:

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

TypeError: n.apply is not a function (https://esm.sh/v135/react-dom@18.3.1/es2022/react-dom.mjs:9)

## 8. 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).

TypeError: n.apply is not a function (https://esm.sh/v135/react-dom@18.3.1/es2022/react-dom.mjs:9)

P.S. I haven’t finished yet; I just want to handle these errors before the code gets messier. :blush:

You have two closing tags on one of your button elements.

Well I guess that isnt it although that self closing opening tag is coming in as an error on code pen.

No, nothing wrong on there, one of it for audio element.

1 Like

It works in isolation, so it must be your context. The Calculator is throwing the same error as is your volume control.

Debugging this on Codepen is not something I would want to do.

The calculator is working fine; I’ve passed all the tests for it. You just need to select the FCC Expression mode from the View menu.

Additionally, I don’t understand what the problem is with the volume control. I added the volume control context in the Drum Machine later, but it gives the same test fail without it, and there is nothing wrong with the volumeControl context.

Probably React-18 issue still online, It also gives another error in the 25 + 5 clock challenge too. (I opened a topic for it but fixed it.)

Anyway, it’s okay. Thanks for your help and contributions.

I’ve created this version on codePen. If someone asks why it’s not passing the tests, I’ll refer them to this link. :sweat_smile:

It might be passing the test, but all your apps are throwing the same error on all button interactions as the drum machine does.

  • The 25+5 clock does it for its buttons

  • The calculator does it for the buttons and menu buttons.

  • The drum machine does it for its buttons and the volume slider.

  • The markdown does it for the menu buttons.

Open the browser console and click the buttons. The same error is thrown for all button interactions.


For the certificate projects, I would suggest you isolate each app and submit them separately. It is a cool app, but it is way out of scope for the certificate projects and all that matter for them is that they are passing the tests (must pass the test for you to submit them).

Alright, the issue isn’t related to the button event listener; it seems to stem from either the draggable Div or context after the last patch. It triggers the same error whether you click on the window, button, or elsewhere. :sweat_smile: I’ll address it accordingly. Thanks for bringing it up.

You’re correct about the tests. If I couldn’t pass them initially, I separate them out but it can still work. It’s all about making it more aesthetically pleasing and challenging :grin:

Okay, I’ve identified the reason for this error. I’m using the same draggable event listener component for both the windows and shortcuts inside of the DraggableDiv. Also, if the top state is true, the onMouseDown handler renders only on the title bar. However, if top is not true, this handler is mounted on the main div of the draggable div with this line:

284-     onMouseDown={!top && handleMouseDown} //this...!!!

Sometimes, taking the easy way out isn’t always the best approach :sweat_smile::sweat_smile:

 onMouseDown={!top ? handleMouseDown : undefined} 

I’ve fixed it, and the drum machine test passed with this solution! :partying_face::partying_face:
Thank you so much, I didn’t realize this for a very long time :sweat_smile: