Home > other >  Why is audo clip not playing on document.getElementById().play()
Why is audo clip not playing on document.getElementById().play()

Time:01-09

I am trying to build a drum-machine in React. When I click a button I would like the audio clip of the child to play. To do this I am passing the id the button and audio to a method when clicked, and then using document.getElementById(Id).play(). However, this does not work. Am I in the right ballpark here or totally wrong?

import * as React from "https://cdn.skypack.dev/[email protected]";
import * as ReactDOM from "https://cdn.skypack.dev/[email protected]";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.playClip = this.playClip.bind(this);
  }
  
  playClip = (e) => {
    const id = event.target.id;
    document.getElementById(id).play();
  }
  
  render() {
    return(
      <div className="container" id="drum-machine">
        <h3>My drum-machine</h3>
        
        <div  id="display">
          <button className="drum-pad" id="Q" onClick={this.playClip}>Q<audio className="clip" src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react-dom.min.js" id="Q" /></button>
          <button className="drum-pad" id="W" onClick={this.playClip}>W<audio className="clip" src="" id="W" /></button>
          <button className="drum-pad" id="E" onClick={this.playClip}>E<audio className="clip" src="" id="E" /></button>
          <button className="drum-pad" id="A" onClick={this.playClip}>A<audio className="clip" src="" id="A" /></button>
          <button className="drum-pad" id="S" onClick={this.playClip}>S<audio className="clip" src="" id="S" /></button>
          <button className="drum-pad" id="D" onClick={this.playClip}>D<audio className="clip" src="" id="D" /></button>
          <button className="drum-pad" id="Z" onClick={this.playClip}>Z<audio className="clip" src="" id="Z" /></button>
          <button className="drum-pad" id="X" onClick={this.playClip}>X<audio className="clip" src="" id="X" /></button>
          <button className="drum-pad" id="C" onClick={this.playClip}>C<audio className="clip" src="" id="C" /></button>
        </div>
      
      </div>
    )
  }
  
}


ReactDOM.render(<App />, document.getElementById("drum-machine"));

CodePudding user response:

You're calling the play method on the button instead of on the audio element.

(When you have invalid HTML with duplicate ids, getElementById will find the first match).

You could hack this with document.getElementById(id).querySelector('audio').play();

But it would be cleaner to make the button and everything in it a component and use a ref.

const AudioButton = ({letter, src}) => {
    const audioElement = useRef(null);
    const onButtonClick = () => {
        audioElement.current.play();
    }
    return (
        <button className="drum-pad" onClick={onButtonClick}>
            {letter}
            <audio className="clip" src={src} />
        </button>
    );
}

and then:

<div  id="display">
    <AudioButton letter="Q" src="q.mp3" />
    <AudioButton letter="W" src="w.mp3" />
    etc
</div>

CodePudding user response:

Your IDs should be all unique. You are calling play on button element and not a child audio element as they both have the same id. Also as you are already getting target after the click event you don't need to search it by ID again. The event will pass you the target element, and you can get its child audio element.

playClip = (e) => {
    const id = event.target.id;
    document.getElementById(id).play();
  }

this method does not work as you are passing e but then are using non existing in the scope event variable. It should be both e or event. My version would be:

playClip = (e) => {
    e.target.querySelector("audio").play();
  }

then you don't need the ID on audio elements at all as long as each button has a child audio element.

  •  Tags:  
  • Related