Drum Machine Test 7 is failing

For some reason, my test 7 on my drum machine keeps failing, despite the preview being updated on my screen. Everything else is working . I’ve tried using dangerouslySetInnerHTML as well as using {displayDescription} within the div element.
Here’s the error message:

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

Here’s my parent:

import React,{useState} from "react";
import './App.css';
import ButtonDrum from "./Components/ButtonDrum";
import MyErrorBoundary from "./MyErrorBoundary";

const App=()=>{
    //importing audio clips, label is the name for the key, displaydescription is for the name of the clip, and file link is the link
    const audioClips=[
        {label: "Q", displayDescription:"amongus", fileLink:"https://drive.google.com/uc?export=download&id=1cQybTYGAU7h2cvSCuIuDR0jU51FXmGfe"},
        {label:"W", displayDescription:"bingchilling", fileLink:"https://drive.google.com/uc?export=download&id=19mxQPg9-7sbNDv25QElzM9NoZN5dCfY9"},
        {label:"E", displayDescription:"carrot", fileLink:"https://drive.google.com/uc?export=download&id=1YlMKfsjAAH-nLWRXLfguZjAzQfLuojgZ"},
        {label: "A", displayDescription:"china", fileLink:"https://drive.google.com/uc?export=download&id=1Fpou-9zit_5uppV6aEzVehPqTW9_o2wb"},
        {label:"S", displayDescription:"nani", fileLink:"https://drive.google.com/uc?export=download&id=1Jlt0LNiwCDpov-Z6DTF48OBuoowU8Jbx"},
        {label:"D", displayDescription:"sharingan", fileLink:"https://drive.google.com/uc?export=download&id=1f908gDa2ekFzbGHUNhy00CB12oUIwFfI"},
        {label: "Z", displayDescription:"uwu", fileLink:"https://drive.google.com/uc?export=download&id=1DUCmYRFzSYfZeaf8mSVmxOcDWwHVBWCE"},
        {label:"X", displayDescription:"wow", fileLink:"https://drive.google.com/uc?export=download&id=1IG082FEfx73n5PEUUFihdjlLK5JqywyR"},
        {label:"C", displayDescription:"yo", fileLink:"https://drive.google.com/uc?export=download&id=1JIqPwLjwF2Gx7pXKAf2Iw0y12F0EnmTb"},
    ];
    //used for updating the div with the display description as text
    const [displayDescription, setDisplayDescription]=useState("Click a button!");
    return(
        //maps each audio clip to a button, unique key is the label, each audio clip object is passed into the button, and the setDisplayDescription function is sent in so that when a button is clicked, it updates on screen
    <div id= "drum-machine">
        <MyErrorBoundary>
        <h1>meme soundboard</h1>
        <div id="display" dangerouslySetInnerHTML={{__html:displayDescription}}>
        </div>
        <div id="buttonContainer">
            {audioClips.map((clip)=>(
                <ButtonDrum setDisplayDescription={setDisplayDescription} key= {clip.label} clip={clip} />
            ))}
        </div>
        </MyErrorBoundary>
    </div>);
}

export default App

as well as the child component:

import React from "react";

const ButtonDrum=({clip, setDisplayDescription})=>{
    //used to check event letter, and see if it matches the button's label
    const handleKeyPress=(event)=>{
        if(event.keyCode===clip.label.charCodeAt(0)){
            playAudioClips();
        }
    }
    React.useEffect(()=>{
        document.addEventListener("keydown", handleKeyPress);
        return()=>{
            document.removeEventListener("keydown",handleKeyPress);
        }
    });
    //updates preview description on click, and plays the audio
    const playAudioClips=()=>{
        setDisplayDescription(clip.displayDescription);
        let newClip=document.getElementById(clip.label);
        newClip.play();
    }
    return(
        <div>
            <button 
            className="drum-pad btn btn-primary p-4 m-3"
            id={clip.displayDescription}
            onClick= {()=>playAudioClips()}
            >
                <audio className="clip" id={clip.label} src={clip.fileLink}></audio>
                {clip.label}
            </button>
        </div>
    )
}
export default ButtonDrum;

It’s easier for others to help if you send the link to your codepen.

Here’s the project itself: React App

and the source code: GitHub - CardinalCyn/drummachine at master

Have a look at the tests themselves:
testable-projects-fcc/drum-machine-tests.js at main · freeCodeCamp/testable-projects-fcc (github.com)

I think I found the issue, it’s likely tied to the fact that my component uses setState to modify the useState of a parent component, causing the page to rerender. Unfortunately, this required me to completely redo everything to find it out. Thanks for the help!

It appears related to React 18. More info.


In your code, I can fix it using flushSync

import { flushSync } from 'react-dom';

const playAudioClips = () => {
  flushSync(() => {
    setDisplayDescription(clip.displayDescription);
  });
  let newClip = document.getElementById(clip.label);
  newClip.play();
};

As an aside, I would suggest you move the logic out of the button component and into App. It really doesn’t belong there, especially not the event listener setup.

Thanks a lot for the help! I moved the logic to the App.js, as well as added the flushSync.

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.