I have a simple React ponent that should play audio via the Web Audio API on keyDown, and stop the audio on keyUp. I have a JSFiddle that shows the same behavior I'm seeing on localhost. Here's the code inline:
var Keyboard = React.createClass({
ponentDidMount: function () {
var context = new (window.AudioContext || window.webkitAudioContext)();
var oscillator = context.createOscillator();
var gain = context.createGain();
oscillator.type = 'sine';
oscillator.frequency.value = 3000;
gain.gain.value = 0.5;
oscillator.connect(gain);
gain.connect(context.destination);
this.setState({
context: context,
oscillator: oscillator,
gain: gain
});
},
render: function() {
return (
<div id="keyboard"
onKeyDown={this.playNote}
onKeyUp={this.stopNote}>
</div>
);
},
playNote: function (ev) {
console.log('play');
this.state.oscillator.start();
},
stopNote: function (ev) {
console.log('stop');
this.state.oscillator.stop();
}
});
React.render(<Keyboard />, document.getElementById('container'));
Even without the Web Audio stuff, I can't get the log statements to show up. I've read the React Event System docs and didn't see anything that would help, and I've written other React ponents using mouse and change events with no problem -- it seems to be particular to keyboard events. Any help would be greatly appreciated!
Edit: Corrected web audio API call. Should've been start(), not play().
I have a simple React ponent that should play audio via the Web Audio API on keyDown, and stop the audio on keyUp. I have a JSFiddle that shows the same behavior I'm seeing on localhost. Here's the code inline:
var Keyboard = React.createClass({
ponentDidMount: function () {
var context = new (window.AudioContext || window.webkitAudioContext)();
var oscillator = context.createOscillator();
var gain = context.createGain();
oscillator.type = 'sine';
oscillator.frequency.value = 3000;
gain.gain.value = 0.5;
oscillator.connect(gain);
gain.connect(context.destination);
this.setState({
context: context,
oscillator: oscillator,
gain: gain
});
},
render: function() {
return (
<div id="keyboard"
onKeyDown={this.playNote}
onKeyUp={this.stopNote}>
</div>
);
},
playNote: function (ev) {
console.log('play');
this.state.oscillator.start();
},
stopNote: function (ev) {
console.log('stop');
this.state.oscillator.stop();
}
});
React.render(<Keyboard />, document.getElementById('container'));
Even without the Web Audio stuff, I can't get the log statements to show up. I've read the React Event System docs and didn't see anything that would help, and I've written other React ponents using mouse and change events with no problem -- it seems to be particular to keyboard events. Any help would be greatly appreciated!
Edit: Corrected web audio API call. Should've been start(), not play().
Share Improve this question edited Jun 5, 2015 at 23:17 Austin Pocus asked Jun 5, 2015 at 23:11 Austin PocusAustin Pocus 99311 silver badges18 bronze badges2 Answers
Reset to default 11A <div>
is a container element, not an input
element. Keyboard events are only generated by <inputs>
, <textarea>
and anything with the contentEditable
attribute.
You could try
render: function() {
return (
<div id="keyboard"
contentEditable={true}
onKeyDown={this.playNote}
onKeyUp={this.stopNote}>
</div>
);
}
but this isn't a guaranteed solution.. just a starting point :)
I just had this problem and found two solutions:
Direct
As mentioned in a similar SO question "onKeyDown event not working on divs in React" (and also in the ments by ncubica), include tabIndex="0"
, for instance:
<div
id="keyboard"
tabIndex="0"
onKeyDown={this.playNote}
onKeyUp={this.stopNote}>
</div>
Work-around
Just add a vanillaJS eventListener()
to your ponentWillMount()
lifecycle and that will load the event listener whenever your page renders (details here: Adding Lifecycle Methods to a Class)
document.addEventListener("keydown", this.playNote);
document.addEventListener("keyup", this.stopNote);