I need to capture cmd button up and down events, in order to choose, whether to use concatenation or not in setState. How do i get these events, for example, on table element?
-
Alternate solution: [onKeyDown event not working on divs in React](https://stackoverflow.com/questions/43503964/onkeydown-event-not-working-on-divs-in-react) – Henry Woody Feb 26 '21 at 23:54
2 Answers
You have to capture the keypress then in body/window level. Table element doesn't have input focus so you can't capture the keys from table (without input element).
var cmdDown = false;
document.body.addEventListener('keydown', function(event) {
var key = event.keyCode || event.charCode || 0;
if ([91,93,224,17].indexOf(key) !== -1) {
cmdDown = true;
}
console.log('CMD DOWN: ' + cmdDown.toString());
});
document.body.addEventListener('keyup', function(event) {
var key = event.keyCode || event.charCode || 0;
if ([91,93,224,17].indexOf(key) !== -1) {
cmdDown = false;
}
console.log('CMD DOWN: ' + cmdDown.toString());
});

- 5,590
- 2
- 18
- 27
-
is this the only way to do it? i have to add listener to body inside componentDidMount? – Taras Lukavyi Aug 25 '16 at 03:12
-
React is javascript.. so yes! Just add the listener in `componentDidMount` and remove it when component is unmounting.. – Hardy Aug 25 '16 at 03:17
Simple Example
I believe best practice here is to add an event listener to document
and modify your element (e.x. table) accordingly. Extending u/Hardy's answer with a full React component:
class MyComponent extends React.Component {
// Using an arrow function. Alternatively, could bind() this
// function in the component's constructor
keydownHandler = (event) => {
// Add logic, e.x. check event.keyCode to see
// if CMD is pressed and then update state
}
componentDidMount() {
document.addEventListener("keydown", this.keydownHandler);
}
componentWillUnmount() {
this.removeEventListener("keydown", this.keydownHandler);
}
render() {
<div>Hello World</div>
}
}
Alternative
As others have noted, there are challenges in using keyboard events that are bound to non-input elements, as browsers require those elements to be in focus in order to invoke the bound callbacks. Another approach that seems to work is to set the tabindex
property of the component to bring the element in focus. From u/burak's answer:
render() {
<div onKeyDown={this.keydownHandler} tabindex={-1}>Example</div>
}
This has the benefit of connecting into React's Synthetic Events, that is "a cross-browser wrapper around the browser’s native event." However, when modifying the tabindex
property it's important to be mindful that this could change the order of focusable elements, and affect a user's ability to navigate your site with their keyboard or accessibility software. Some users report that setting tabindex
to -1
resolves this issue (see comments in previous link).

- 5,800
- 1
- 44
- 40
-
this is only part of the solution as it's also affecting input fields – BenjaminK Sep 09 '21 at 11:47
-