Drum Machine Repeating Sound

Hello,

I’m working on the Drum Machine, one of the front end projects. on my best attempt, I have been able to make each button play a sound at a click. However, I got it to work by setting a state property to the id of each button inside the click handler so it’s updated to the id of the newly clicked button. So the problem is, it doesn’t update the state at the first click of another button, thereby playing the same sound once more.

Here is the link to my codepen: https://codepen.io/idrisishola/pen/yLvwbbZ

Why not just switch on event.target.id it really doesn’t have to be state. Are you going to use it for the UI?

You can also add the code inside a setState callback

this.setState({stateProp: stateValue}, () => // callbackCode)

handleClick(event) {
  this.setState(
    {
      buttonClicked: event.target.id
    },
    () => {
      console.log(this.state.buttonClicked);
      switch (this.state.buttonClicked) {
        case "beast-roar":
          this.beastRoarRef.current.play();
          break;
        case "fast-rocket":
          this.fastRocketRef.current.play();
          break;
        case "dog-barking":
          this.dogBarkingRef.current.play();
          break;
        case "wild-lion":
          this.wildLionRef.current.play();
          break;
        case "retro-game":
          this.retroGameRef.current.play();
          break;
        case "alarm-tone":
          this.alarmToneRef.current.play();
          break;
        case "classic-alarm":
          this.classicAlarmRef.current.play();
          break;
        case "arcade-retro":
          this.arcadeRetroRef.current.play();
          break;
        case "fast-small":
          this.fastSmallRef.current.play();
          break;
        default:
          return null;
      }
    }
  );
}

Thanks a lot for your quick response. It’s working very well now. I appreciate your help.

Just another question, is my use of ref correct or the best way to use it in this case. I was wondering if there’s a away I could make the references shorter and compact rather referencing each element using a separate code.

You can use an array of refs. If you pass the ref prop a function (callback ref) it will be passed the element(s) on mount and you can push them to an array.

You can also skip using refs and just use the click target to get to the child audio element event.target.firstElementChild

Example code:

Amazing! much appreciation :clap: Thanks alot.

Could you help me with some hints on this one? Upon pressing a button, a text for the triggered audio should be displayed in another element. And I have this element as a seperate component. So I don’t know how I may tie thi s component to the event that triggers the audio. thank you

Where is your current code?


  1. Create state inside DrumMachine for the display name.

  2. Create a function inside DrumMachine that sets the display name state.

  3. Pass down the function which sets the state from DrumMachine as a prop to DrumPads. Call it inside DrumPads and pass it the value.

  4. Pass down the display name state from DrumMachine, as a prop, to Display and then down to Title. Use the prop inside Title.


I’m not sure I can really explain it better than that without posting some code. I would suggest you read the React docs on Lifting State Up and see if you can make sense of it with the explanation I gave.

I understood your explanation to an extent but find it diffult it to implement from a certain point. I understand I have to set the display name in the DrumMachine using the function. I’m not sure what to set it to.
Here is my codepen: https://codepen.io/idrisishola/pen/yLvwbbZ

The function inside DrumMachine needs to use the value it is passed as an argument for the setState call.

DrumMachine component:

displayName(name) {
  this.setState({
    audioName: name
  });
}

You need to pass the function and the state to the two components inside DrumMachine as props.

DrumMachine component:

<DrumPads displayName={this.displayName}/>
<Display soundName={this.state.audioName}/>

After that you now have access to this.props.displayName() inside DrumPads. You can call that function before the switch and pass it the name to set.

this.props.displayName(name)

What you use for the name (the value you are going to pass to the displayName function) is up to you. But one option is to use the id on the button (the click target) event.target.id, you might split it on - and then join it back on a space.

If you want the Title component to display the name you have to pass it down one more time from Display to Title

Display component:

<Title soundName={props.soundName}/>

Here is a simple example that shows the basic idea.

Thanks so much for your help. I really appreciate it. It’s working now.

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