Daniel Bogdan Oprea
Daniel Bogdan Oprea

Reputation: 25

ReactJS - How do I play an audio element onKeyPress and onClick?

So I am trying to build the Drum Machine project from freeCodeCamp and I have encountered this issue with the audio element. I wrote the code below. I get no errors whatsoever, but the audio still doesn't play when I click the div with the class "drum-pad". I know how to make this work without the audio element, but the challenge requires the use of the element specifically.

I will still try to figure this out for myself and I will update this issue if I found a solution elsewhere.

This is my DrumPad component

import React from 'react';

class DrumPad extends React.Component {
    constructor(props){
        super(props);
        this.state = {
            name: this.props.name,
            audio: this.props.source,
            indexNr: this.props.indexNr,
            keyId: this.props.keyId
        }
        this.clickHandle = this.clickHandle.bind(this);
        this.keyPressHandle = this.keyPressHandle.bind(this);
    }


    clickHandle() {
        document.getElementById(`audio${this.state.indexNr}`).play();
    }

    keyPressHandle(event) {
        if(event.key === this.state.keyId || event.key === this.state.keyId.toLowerCase()){
            document.getElementById(`audio${this.state.indexNr}`).play();
        }
    }

    render(){
        return (
            <div className="drum-pad" id={this.name} onClick={this.clickHandle} onKeyPress={this.keyPressHandle}>
                    <h3>{this.state.keyId}</h3>
                    <audio id={`audio${this.state.indexNr}`} src={this.audio} />
            </div>
        )
    }
}

export default DrumPad; 

This is my Keyboard component

import DrumPad from "./DrumpPad";

const Keyboard = (props) => {
    return <div className="column1">
        { 
            soundsArr.map((sound, index) => <DrumPad key={index} indexNr={index} name={sound.name} source={sound.source} keyId={sound.keyId} />) 
        }
    </div>
}

export default Keyboard;


const soundsArr = [
    {
      name: "Drum0", 
      source: "https://s3.amazonaws.com/freecodecamp/drums/Heater-6.mp3",
      keyId: "Q"
    },
    {
      name: "Drum1", 
      source: "https://s3.amazonaws.com/freecodecamp/drums/Heater-6.mp3",
      keyId: "W"
    },
    {
      name: "Drum2", 
      source: "https://s3.amazonaws.com/freecodecamp/drums/Heater-6.mp3",
      keyId: "E"
    },
    {
      name: "Drum3", 
      source: "https://s3.amazonaws.com/freecodecamp/drums/Heater-6.mp3",
      keyId: "A"
    },
    {
      name: "Drum4", 
      source: "https://s3.amazonaws.com/freecodecamp/drums/Heater-6.mp3",
      keyId: "S"
    },
    {
      name: "Drum5", 
      source: "https://s3.amazonaws.com/freecodecamp/drums/Heater-6.mp3",
      keyId: "D"
    },
    {
      name: "Drum6", 
      source: "https://s3.amazonaws.com/freecodecamp/drums/Heater-6.mp3",
      keyId: "Z"
    },
    {
      name: "Drum7", 
      source: "https://s3.amazonaws.com/freecodecamp/drums/Heater-6.mp3",
      keyId: "X"
    },
    {
      name: "Drum8", 
      source: "https://s3.amazonaws.com/freecodecamp/drums/Heater-6.mp3",
      keyId: "C"
    }
  ];

Upvotes: 2

Views: 997

Answers (1)

a.mola
a.mola

Reputation: 4011

It's a lot. But here's how I edited the code.

Edit pedantic-lumiere-cpt3s


  • In the DrumPad component, you added all your props to state. That isn't needed because you didn't change any of the values, so its best to convert the component from a Class to a Function component.
  • You added an onKeyPress event to the parent div element in the DrumPad component. That won't ever run because the element cannot be focused on. So you should use a useEffect hook to attach the event to the window and play the audio.
  • It is not advised to use the index of an array as its key prop. You should use name and keyId of the DrumPad as it is already unique. In the render function of the Keyboard component.
  • From the previous point, you can use the key or name to generate the audio's id. Meaning there won't be need to pass the indexNr prop. Or you can use the useRef hook to access the audio

Upvotes: 1

Related Questions