145 votes

L'événement onKeyDown ne fonctionne pas sur les divs dans React

Je veux utiliser un événement keyDown sur un div dans React. Je le fais :

  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>
    )
  }

Cela fonctionne bien, mais j'aimerais le faire plus dans le style React. J'ai essayé

        onKeyDown={this.onKeyPressed}

sur le composant. Mais il ne réagit pas. Il fonctionne sur les éléments d'entrée si je me souviens bien.

Codepen

Comment puis-je le faire ?

1 votes

Personnellement, j'aime votre approche. Elle semble être un bon moyen de lier les frappes de touches au document, ce qui est en dehors de la portée de votre composant et ne nécessite pas de se concentrer sur un élément particulier.

222voto

burakhan alkan Points 1545

Vous devez utiliser tabIndex attribut pour pouvoir écouter onKeyDown sur un div en React. Réglage de tabIndex="0" devrait renvoyer votre gestionnaire.

5 votes

Cela ressemble à une mauvaise conception, à une opinion. Que faire si je veux gérer un événement de bulle sur un élément conteneur mais que ce conteneur lui-même ne doit jamais être focalisé ?

1 votes

Cela ressemble plus à un hack ou à une solution de contournement pour moi. Il peut arriver que vous ayez besoin que la div donnée maintienne un ordre de tabulation.

28 votes

tabIndex={-1} peut également être utilisé si vous travaillez avec un élément qui n'est pas interactif et que vous ne souhaitez pas modifier l'ordre des tabulations du document.

29voto

Panther Points 4678

Vous devez l'écrire de cette façon

<div 
    className="player"
    style={{ position: "absolute" }}
    onKeyDown={this.onKeyPressed}
    tabIndex="0"
  >

Si onKeyPressed n'est pas lié à this puis essayez de le réécrire en utilisant la fonction flèche ou en le liant au composant. constructor .

2 votes

Désolé. J'étais sûr, j'ai juste négligé ceci. Mais ce n'est pas le problème. Ça ne marche toujours pas.

0 votes

Réponse actualisée. Vous devez soit cliquer sur la division, soit la mettre en évidence avant d'appuyer sur une touche.

0 votes

Je l'ai fait. Cela ne fonctionne pas. J'ai mis à jour le code ci-dessus. Il fonctionne bien avec les commandes DOM, mais pas dans le style React.

10voto

steel Points 793

Vous pensez trop en Javascript pur. Débarrassez-vous de vos écouteurs sur ces méthodes du cycle de vie de React et utilisez event.key au lieu de event.keyCode (parce que ce n'est pas un objet d'événement JS, c'est un objet React SyntheticEvent ). Votre composant entier pourrait être aussi simple que cela (en supposant que vous n'avez pas lié vos méthodes dans un constructeur).

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>
  )
}

0 votes

C'est exactement comme ça que je voulais l'écrire. Mais bon sang, ça ne va pas. Voici le codepen : codepen.io/lafisrap/pen/OmyBYG . Si vous commentez la ligne 275, l'entrée par le clavier (touches de curseur) ne fonctionne pas. onKeyDown est à la ligne 307.

0 votes

KeyCode que j'utilise pour les touches de curseur, car elles ne renvoient aucun caractère.

1 votes

React n'utilise pas les objets d'événements Javascript, donc il n'y a pas de propriété keyCode. Cela event est un objet React SyntheticEvent .

5voto

Muppet Points 549

Utilisation de la div tour avec tab_index="0" o tabIndex="-1" fonctionne, mais chaque fois que l'utilisateur met au point une vue qui n'est pas un élément, vous obtenez un affreux focus-outline sur l'ensemble du site Web. Pour remédier à ce problème, il suffit d'utiliser la feuille de style en cascade (CSS) de la division. outline: none dans le foyer.

Voici l'implémentation avec des composants stylisés :

import styled from "styled-components"

const KeyReceiver = styled.div`
  &:focus {
    outline: none;
  }
`

et dans la classe App :

  render() {
    return (      
      <KeyReceiver onKeyDown={this.handleKeyPress} tabIndex={-1}>
          Display stuff...
      </KeyReceiver>
    )

3voto

busybee Points 101

La réponse avec

<div 
    className="player"
    onKeyDown={this.onKeyPressed}
    tabIndex={0}
>

fonctionne pour moi, veuillez noter que le tabIndex nécessite un nombre, pas une chaîne de caractères, donc tabIndex="0" ne fonctionne pas.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X