Quiero usar un evento keyDown en un div en React. Hago:
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>
)
}
Funciona bien, pero me gustaría hacerlo más al estilo React. Lo intenté
onKeyDown={this.onKeyPressed}
en el componente. Pero no reacciona. Funciona en elementos de entrada, según recuerdo.
¿Cómo puedo hacerlo?

Respuestas:
Debe usar el atributo tabIndex para poder escuchar el
onKeyDownevento en un div en React. La configuracióntabIndex="0"debería despedir a su manejador.fuente
tabIndex={-1}también se puede usar si está trabajando con un elemento que no es interactivo y no desea cambiar el orden de tabulación del documento.Necesitas escribirlo de esta manera
<div className="player" style={{ position: "absolute" }} onKeyDown={this.onKeyPressed} tabIndex="0" >Si
onKeyPressedno está vinculado athis, intente reescribirlo usando la función de flecha o vincularlo en el componenteconstructor.fuente
console.logno genera nada?Estás pensando demasiado en Javascript puro. Deshágase de sus oyentes en esos métodos de ciclo de vida de React y utilícelos en
event.keylugar deevent.keyCode(porque este no es un objeto de evento JS, es un React SyntheticEvent ). Todo su componente podría ser tan simple como esto (suponiendo que no haya vinculado sus métodos en un 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> ) }fuente
eventobjeto es un React SyntheticEvent .onClickaccesorio en lugar delonKeyDowncontrolador se dispara.La respuesta con
<div className="player" onKeyDown={this.onKeyPressed} tabIndex={0} >funciona para mí, tenga en cuenta que tabIndex requiere un número, no una cadena, por lo que tabIndex = "0" no funciona.
fuente
Usar el
divtruco contab_index="0"otabIndex="-1"funciona, pero cada vez que el usuario enfoca una vista que no es un elemento, obtienes un esquema de enfoque feo en todo el sitio web. Esto se puede solucionar configurando el CSS para que el div lo useoutline: noneen el foco.Aquí está la implementación con componentes con estilo:
import styled from "styled-components" const KeyReceiver = styled.div` &:focus { outline: none; } `y en la clase App:
render() { return ( <KeyReceiver onKeyDown={this.handleKeyPress} tabIndex={-1}> Display stuff... </KeyReceiver> )fuente
Falta el enlace del método en el constructor. Así es como React sugiere que lo hagas:
class Whatever { constructor() { super(); this.onKeyPressed = this.onKeyPressed.bind(this); } onKeyPressed(e) { // your code ... } render() { return (<div onKeyDown={this.onKeyPressed} />); } }Hay otras formas de hacer esto, pero esta será la más eficiente en tiempo de ejecución.
fuente
Debe evitar que se active el evento predeterminado.
onKeyPressed(e) { e.preventDefault(); console.log(e.key); }fuente