0
votes

I am working on a Drum machine project where I am failing to pass a task. the task is:

When I press the trigger key associated with each .drum-pad, the audio clip contained in its child 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.).

My code so far:

class Drumset extends React.Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
    this.handleKeyPress = this.handleKeyPress.bind(this);
  }
  componentDidMount() {
    document.addEventListener("keydown", this.handleKeyPress);
  }

  handleClick = (event) => {
    const audio = event.target.children[0];
    audio.play();
  };

  handleKeyPress = (event) => {
    if (
      event.key === "q" ||
      event.key === "w" ||
      event.key === "e" ||
      event.key === "a" ||
      event.key === "s" ||
      event.key === "d" ||
      event.key === "z" ||
      event.key === "x" ||
      event.key === "c"
    ) {
      const audio = event.target.children[0];
      audio.play;
      console.log("key pressed");
    }
  };

  render() {
    return (
      <div>
        <div id="drum-machine" class="containerx box-middle">
          <div id="display" onKeyDown={this.handleKeyPress}>
            <div class="container">
              <div class="row">
                <div class="col">
                  <button
                    type="button"
                    class="drum-pad"
                    id="Heater-1"
                    onClick={this.handleClick}
                  >
                    Q
                    <audio
                      class="clip"
                      id="Q"
                      src="https://s3.amazonaws.com/freecodecamp/drums/Heater-1.mp3"
                      type="audio/mpeg"
                    ></audio>
                  </button>

My problem is that, whenever I press a key, the handleKeyPress() function works but the audio doesn't play (the console shows the print). How to play the audio when I press the associated button?

1
audio.play; does nothing, just references the function. Did you mean audio.play()? - ggorlen
@ggorlen getting an error in console that says audio.play() is not a function whenever I run the code. - tanjim anim
@tanjimanim: Your problem is solved, use the answer that I provided. Also if you need any further explanation, do reach out to me brother :). Do accept the answer and rate as well for other developers to benefit from this :) Thanks - Imran Rafiq Rather
@ImranRafiqRather thanks brother - tanjim anim
Most Welcome brother. Allah bless you :) Do please rate my answer and accept it also by clicking the tick icon. That will motivate me more and also help other developers with the same problem :) - Imran Rafiq Rather

1 Answers

1
votes

The problem is this : in your handleKeyPress handler, const audio = event.target.children[0]; does not target the audio element.

I have used ref to target the audio once user clicks on any of the keys mentioned in handleKeyPress. Also whenever we use onKeyDown synthetic event, we must use tabIndex={0}. Try the below code :)

import React, { Component } from "react";

export default class DrumSet extends Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
  }
  componentDidMount() {
    document.addEventListener("keydown", this.handleKeyPress);
  }
  handleKeyPress = (event) => {
    console.log(event.key);
    if (
      event.key === "q" ||
      event.key === "w" ||
      event.key === "e" ||
      event.key === "a" ||
      event.key === "s" ||
      event.key === "d" ||
      event.key === "z" ||
      event.key === "x" ||
      event.key === "c"
    ) {
      this.myRef.current.play();
      console.log("key pressed");
    }
  };
  handleClick = (event) => {
    const audio = event.target.children[0];
    audio.play();
  };
  render() {
    return (
      <div>
        <div id="drum-machine" className="containerx box-middle">
          <div id="display" onKeyDown={this.handleKeyPress} tabIndex={0}>
            <div className="container">
              <div className="row">
                <div className="col">
                  <button type="button" className="drum-pad" id="Heater-1">
                    Q
                    <audio
                      className="clip"
                      id="Q"
                      src="https://s3.amazonaws.com/freecodecamp/drums/Heater-1.mp3"
                      type="audio/mpeg"
                      ref={this.myRef}
                    ></audio>
                  </button>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    );
  }
}