I'm trying to learn React by making a simple "sound machine".
Well, I want that when a key is pressed or any of the .drum-pads is clicked, this class is activated (let's say that the class would be activated in each of the .drum-pad divs )
.onclickonkeyed{
background: white;
-webkit-transition: background-color 300ms linear;
-ms-transition: background-color 300ms linear;
transition: background-color 300ms linear;
}
Can that be done at once?
Or how should it be done?
I have this at the moment:
class DrumPad extends React.Component{
constructor(props){
super(props)
}
render(){
return(
<div id="grid-keys">
<div className="drum-pad" id="Heater-1"><audio src="" className="clip" id="Q"></audio>Q</div>
<div className="drum-pad" id="Heater-2"><audio src="" className="clip" id="W"></audio>W</div>
<div className="drum-pad" id="Heater-3"><audio src="" className="clip" id="E"></audio>E</div>
<div className="drum-pad" id="Heater-4"><audio src="" className="clip" id="A"></audio>A</div>
<div className="drum-pad" id="Clap"><audio src="" className="clip" id="S"></audio>S</div>
<div className="drum-pad" id="Open-HH"><audio src="" className="clip" id="D"></audio>D</div>
<div className="drum-pad" id="Kick-n'-Hat"><audio src="" className="clip" id="Z"></audio>Z</div>
<div className="drum-pad" id="Kick"><audio src="" className="clip" id="X"></audio>X</div>
<div className="drum-pad" id="Closed-HH"><audio src="" className="clip" id="C"></audio>C</div>
</div>
)
}
}
class App extends React.Component {
constructor(props){
super(props)
}
render(){
return (
<div id="drum-machine">
<DrumPad />
<div id="display">"SOUND"</div>
</div>
)
}
}
ReactDOM.render(<App/>, document.getElementById('root'))
body{
background:
linear-gradient(135deg, #708090 21px, #d9ecff 22px, #d9ecff 24px, transparent 24px, transparent 67px, #d9ecff 67px, #d9ecff 69px, transparent 69px),
linear-gradient(225deg, #708090 21px, #d9ecff 22px, #d9ecff 24px, transparent 24px, transparent 67px, #d9ecff 67px, #d9ecff 69px, transparent 69px)0 64px;
background-color:#708090;
background-size: 64px 128px;
}
#drum-machine{
width: 40%;
margin: 0 auto;
padding: 30px;
background: #8C271E;
border: 6px solid #BD632F;
border-radius: 4px;
color: black;
font-weight: bold;
font-family: arial;
display: flex;
}
#display{
font-style: italic;
background: #D9D1D4;
height: 20PX;
width: 70px;
padding: 10px 25px 10px 25px;
border: 2px solid #7C7C7C;
margin-left: 60px;
margin-top: 60px;
}
#grid-keys{
display: grid;
grid-template-columns: repeat(3, 100px);
grid-auto-rows: minmax(50px, auto);
grid-gap: 10px;
}
#grid-keys .drum-pad{
background: #D8973C;
display: flex;
justify-content: center;
align-items: center;
border-radius: 3px;
cursor: pointer;
}
.onclickonkeyed{
background: white;
-webkit-transition: background-color 300ms linear;
-ms-transition: background-color 300ms linear;
transition: background-color 300ms linear;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
I recommend you change your approach. Imagine you add 50 more keys; you would have to type 50
div
manually. Not much fun.Component Key
Create a component that represents a key. This key will receive as a property the letter that it will render.
This class must handle the event
click
. What we will do is add the classactive
if the button has been pressed. After a reasonable amount of time, we will remove the class.First we create the state:
Later, we create the method
highlight
, which will be in charge of updating the state to change the value ofactive
.Now, we will add some variables to the class:
runningAnimation
: indicates if the animation is running and avoid doing a double.HIGHLIGHT_TIMEOUT
: indicates the maximum time that the animation will last.sound
: type variableAudio
that will serve to reference the audio file and execute it.Now, we will create the method that is responsible for firing these actions when the button is pressed:
So far we already have our functional key. If you press the button, the class should be added
active
by producing a pressing animation and playing the sound.Component Keyboard
In this component we are going to render as many components
DrumPad
as letters we have. For this, we are going to save an array of keys in the state:Next, we are going to convert them into components
DrumPad
:And we proceed to register the listeners in
componentDidMount
:If you look, we have created a
ref
for each key and we have saved it in an array variablekeysRefs
, this will help us so that when we press a key on our keyboard, we can obtain the component associated with that key and be able to manually trigger the methodactivate
.Look at the implementation of
onKeyDown
:This is the interesting thing about the
refs
: you can access methods inside the components . This will allow us to use the same logic whether the button was pressed or the key was pressed.Example