score:0

if you save the state of the drum in app you can then pass that prop down to the box component. the box component can decide whether to immediately play the sound, or wait for a click.

but the most important thing is to use useeffect to set up the keydown event on the window, and allow react to drive the code.

i also reduced your css code down by using css grid.

const { useeffect, useref, usestate } = react;

const sounds=[{key:"q",mp3:"https://s3.amazonaws.com/freecodecamp/drums/heater-1.mp3"},{key:"w",mp3:"https://s3.amazonaws.com/freecodecamp/drums/heater-2.mp3"},{key:"e",mp3:"https://s3.amazonaws.com/freecodecamp/drums/heater-3.mp3"},{key:"a",mp3:"https://s3.amazonaws.com/freecodecamp/drums/heater-4_1.mp3"},{key:"s",mp3:"https://s3.amazonaws.com/freecodecamp/drums/heater-6.mp3"},{key:"d",mp3:"https://s3.amazonaws.com/freecodecamp/drums/dsc_oh.mp3"},{key:"z",mp3:"https://s3.amazonaws.com/freecodecamp/drums/kick_n_hat.mp3"},{key:"x",mp3:"https://s3.amazonaws.com/freecodecamp/drums/rp4_kick_1.mp3"},{key:"c",mp3:"https://s3.amazonaws.com/freecodecamp/drums/cev_h2.mp3"}];

// passing in the sounds into the app component
function app({ sounds }) {

  // creating an initial state with an array of
  // keys from the sounds object set to false
  const state = sounds.map(obj => ({ [obj.key]: false }));

  // set that state
  const [ isplaying, setisplaying ] = usestate(state);

  // the useeffect sets up the keydown event on the window
  // when a key is pressed the state is updated, and a render takes place
  useeffect(() => {
    window.addeventlistener('keydown', (e) => {
      setisplaying({ ...isplaying, [e.key.touppercase()]: true });
    });

    // clean up
    return function () {
      window.removeeventlistener('keydown');
    }

  }, []);

  // so now we're passing the property (key)
  // of state down to the box component
  return (
    <div classname="container">
      {sounds.map((sound, idx) => (
        <box
          text={sound.key}
          key={idx}
          audio={sound.mp3}
          isplaying={isplaying[sound.key]}
        />
      ))}
    </div>
  );
}

function box({ text, audio, isplaying }) {

  // still using `ref` but i've changed this to
  // a function component so now we use `useref`
  const ref = useref();

  // play the sound
  function playsound() {
    ref.current.play();
  }

  // if `isplaying` is true play the sound
  if (isplaying) playsound();

  // otherwise wait for the click event on the
  // div and then play the sound
  return (
    <div
      classname="box"
      onclick={playsound}
      >{text}
      <audio ref={ref} src={audio} />
    </div>
  )

}

reactdom.render(
  <app sounds={sounds} />,
  document.getelementbyid('react')
);
.container {
  width: 300px;
  display: grid;
  grid-template-columns: repeat(3, 100px);
}

.box {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 2em;
  background-color: #8e44ad;
  cursor: pointer;
  color: #fff;
  margin: 0.2em;
  padding: 0.2em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>


Related Query

More Query from same tag