onKeyDown event not working on divs in React
Solution 1
You should use tabIndex attribute to be able to listen onKeyDown
event on a div in React. Setting tabIndex="0"
should fire your handler.
Solution 2
You need to write it this way
<div
className="player"
style={{ position: "absolute" }}
onKeyDown={this.onKeyPressed}
tabIndex="0"
>
If onKeyPressed
is not bound to this
, then try to rewrite it using arrow function or bind it in the component constructor
.
Solution 3
You're thinking too much in pure Javascript. Get rid of your listeners on those React lifecycle methods and use event.key
instead of event.keyCode
(because this is not a JS event object, it is a React SyntheticEvent). Your entire component could be as simple as this (assuming you haven't bound your methods in a constructor).
onKeyPressed(e) {
console.log(e.key);
}
render() {
let player = this.props.boards.dungeons[this.props.boards.currentBoard].player;
return (
<div
className="player"
style={{ position: "absolute" }}
onKeyDown={this.onKeyPressed}
>
<div className="light-circle">
<div className="image-wrapper">
<img src={IMG_URL+player.img} />
</div>
</div>
</div>
)
}
Solution 4
Using the div
trick with tab_index="0"
or tabIndex="-1"
works, but any time the user is focusing a view that's not an element, you get an ugly focus-outline on the entire website. This can be fixed by setting the CSS for the div to use outline: none
in the focus.
Here's the implementation with styled components:
import styled from "styled-components"
const KeyReceiver = styled.div`
&:focus {
outline: none;
}
`
and in the App class:
render() {
return (
<KeyReceiver onKeyDown={this.handleKeyPress} tabIndex={-1}>
Display stuff...
</KeyReceiver>
)
Solution 5
The answer with
<div
className="player"
onKeyDown={this.onKeyPressed}
tabIndex={0}
>
works for me, please note that the tabIndex requires a number, not a string, so tabIndex="0" doesn't work.
![Michael](https://i.stack.imgur.com/op6HW.png?s=256&g=1)
Michael
Contradictions are an essence of life. For example time and quality, being serious and having fun, deadlines and details. My favourite polarity is programming and communicating openly without fear. I do both with great enthusiasm. With 17 I programmed video games in a professional environment, with 28 secure online banking applications. Later I developed a web archive and a computer playground. In my portfolio you find a selection of my projects. I’m currently fluent in HTML, CSS, JavaScript, jQuery, React/Redux, node.js, Express, Bootstrap, Hugo. But also eager to learn more.
Updated on July 08, 2022Comments
-
Michael almost 2 years
I want to use a keyDown event on a div in React. I do:
componentWillMount() { document.addEventListener("keydown", this.onKeyPressed.bind(this)); } componentWillUnmount() { document.removeEventListener("keydown", this.onKeyPressed.bind(this)); } onKeyPressed(e) { console.log(e.keyCode); } render() { let player = this.props.boards.dungeons[this.props.boards.currentBoard].player; return ( <div className="player" style={{ position: "absolute" }} onKeyDown={this.onKeyPressed} // not working > <div className="light-circle"> <div className="image-wrapper"> <img src={IMG_URL+player.img} /> </div> </div> </div> ) }
It works fine, but I would like to do it more in React style. I tried
onKeyDown={this.onKeyPressed}
on the component. But it doesn't react. It works on input elements as I recall.
How can I do it?
-
Michael about 7 yearsSorry. I was sure, I just overlooked the this. But this is not the problem. It's still not working.
-
Panther about 7 yearsupdated answer. You should either click on the div or bring it to focus before pressing any keys.
-
Michael about 7 yearsI did. It's not working. I updated the code above. It works fine with the DOM commands, but not in React style.
-
Panther about 7 yearscan you explain what is not working? is your function not getting callled or
console.log
is outputing nothing ? -
Michael about 7 yearsThat's exactly how I wanted to write it. But the hell, it's not going. Here is the codepen: codepen.io/lafisrap/pen/OmyBYG . If you comment line 275 then key board input (cursor keys) is not working. onKeyDown is in line 307.
-
Michael about 7 yearskeyCode I use for cursor keys, as they return no character.
-
Michael about 7 yearsThe function is not called. I have a codepen: codepen.io/lafisrap/pen/OmyBYG . It about lines 275 and 307.
-
steel about 7 yearsReact doesn't use Javascript event objects, so there is no keyCode property. That
event
object is a React SyntheticEvent. -
steel about 7 years@Michael I also am not entirely sure how you are triggering a key event on a div, but when I put this code into a fiddle with an
onClick
prop instead ofonKeyDown
the handler fires. -
Michael about 7 yearsThanks. That explains it ... The key events work in input fields though.
-
steel about 7 yearsI figured, I just couldn't figure out how to do it.
-
Will P. over 4 yearsThis seems like bad, opinionated design. What if I want to handle a bubbling event on a container element but that container itself should not ever be focused?
-
Iwnnay over 4 yearsThis seems like more of a hack or workaround to me. There may be a time when you need to have the given div maintain a tab order.
-
IliasT over 4 years
tabIndex={-1}
can also be used if you're working with an element that isn't interactive and don't want to change the tab order of the document. -
Kavita about 4 yearsyou have to set the tabIndex, to make the div focusable. You can set the tabIndex to 0,1,-1.... But before you do that check this out webaim.org/techniques/keyboard/tabindex You'll likely want to set to -1 since you're manipulating it programmatically.
-
Flion about 4 yearsfor some reason this only works if I have an <input> element in the div with the tabIndex. Or something else that can be focussed. With just other divs, its still not capturing. Any thoughts?
-
busybee over 3 yearsworks for me with tabIndex={0} , tabIndex requires a number, not a string, so tabIndex="0" was flagged as a typescript error
-
picaCHuXX almost 3 yearsadding tabIndex is not working for me, I am trying to get the value from the input and I have this code:
<div onKeyDown={(e) => handleOnKeyDown(e)}>
...here i have custom component that has input value..</div>
Does someone know why what might be the problem?