175 votes

Comment détecter la pression de la touche Echap dans React et comment la gérer ?

Comment détecter une pression sur la touche Esc dans reactjs ? La chose similaire à jquery

$(document).keyup(function(e) {
     if (e.keyCode == 27) { // escape key maps to keycode `27`
        // <DO YOUR WORK HERE>
    }
});

Une fois détecté, je veux transmettre l'information aux composants. J'ai 3 composants dont le dernier composant actif doit réagir à la pression de la touche Echap.

Je pensais à une sorte d'enregistrement de l'activation d'un composant.

class Layout extends React.Component {
  onActive(escFunction){
    this.escFunction = escFunction;
  }
  onEscPress(){
   if(_.isFunction(this.escFunction)){
      this.escFunction()
   }
  }
  render(){
    return (
      <div class="root">
        <ActionPanel onActive={this.onActive.bind(this)}/>
        <DataPanel onActive={this.onActive.bind(this)}/>
        <ResultPanel onActive={this.onActive.bind(this)}/>
      </div>
    )
  }
}

et sur tous les composants

class ActionPanel extends React.Component {
  escFunction(){
   //Do whatever when esc is pressed
  }
  onActive(){
    this.props.onActive(this.escFunction.bind(this));
  }
  render(){
    return (   
      <input onKeyDown={this.onActive.bind(this)}/>
    )
  }
}

Je crois que cela fonctionnera mais je pense que ce sera plutôt un rappel. Y a-t-il une meilleure façon de gérer cela ?

0 votes

N'avez-vous pas une implémentation de flux pour stocker le composant actif au lieu de le faire de cette façon ?

0 votes

@BenHare : Je suis encore assez novice en la matière. J'étudie la possibilité de migrer vers React. Je n'ai pas essayé flux, donc vous suggérez que je devrais regarder dans flux pour la solution. PS : Que diriez-vous de détecter une pression sur la touche ESC ?

5 votes

Pour clarifier, cherchez-vous à détecter les pressions sur les touches au niveau du document, comme le premier bloc de code ? Ou est-ce pour un champ de saisie ? Vous pouvez faire l'un ou l'autre, mais je ne suis pas sûr de savoir comment formuler une réponse. Voici un exemple rapide au niveau du document : codepen.io/anon/pen/ZOzaPW

299voto

Chase Sandmann Points 428

Si vous recherchez un traitement des événements clés au niveau du document, vous pouvez le lier au cours de l'opération suivante componentDidMount est le meilleur moyen (comme le montre L'exemple de codepen de Brad Colthurst ) :

class ActionPanel extends React.Component {
  constructor(props){
    super(props);
    this.escFunction = this.escFunction.bind(this);
  }
  escFunction(event){
    if (event.key === "Escape") {
      //Do whatever when esc is pressed
    }
  }
  componentDidMount(){
    document.addEventListener("keydown", this.escFunction, false);
  }
  componentWillUnmount(){
    document.removeEventListener("keydown", this.escFunction, false);
  }
  render(){
    return (   
      <input/>
    )
  }
}

Notez que vous devez vous assurer de supprimer l'écouteur d'événements de la clé lors du démontage pour éviter les erreurs potentielles et les fuites de mémoire.

EDIT : Si vous utilisez des crochets, vous pouvez utiliser ceci useEffect pour produire un effet similaire :

const ActionPanel = (props) => {
  const escFunction = useCallback((event) => {
    if (event.key === "Escape") {
      //Do whatever when esc is pressed
    }
  }, []);

  useEffect(() => {
    document.addEventListener("keydown", escFunction, false);

    return () => {
      document.removeEventListener("keydown", escFunction, false);
    };
  }, []);

  return (   
    <input />
  )
};

11 votes

Quel est le troisième argument dans addEventListener y removeEventListener ?

2 votes

@jhuang developer.mozilla.org/fr/US/docs/Web/API/EventTarget/ - peuvent être otions ou utiliserCapture

3 votes

@jhuang c'est l'argument useCapture qui spécifie si oui ou non il faut capturer les événements. qui d'habitude ne font pas de bulles comme focus . Ce n'est pas pertinent pour keydown mais il n'était pas facultatif auparavant donc il est généralement spécifié pour la compatibilité avec IE<9.

34voto

pirt Points 345

Vous voudrez écouter l'évasion. keyCode (27) de la React SyntheticKeyBoardEvent onKeyDown :

const EscapeListen = React.createClass({
  handleKeyDown: function(e) {
    if (e.keyCode === 27) {
      console.log('You pressed the escape key!')
    }
  },

  render: function() {
    return (
      <input type='text'
             onKeyDown={this.handleKeyDown} />
    )
  }
})

CodePen de Brad Colthurst affiché dans les commentaires de la question est utile pour trouver les codes des autres clés.

20 votes

Je pense qu'il est utile d'ajouter que React semble no tirer le onKeyPress lorsque la touche pressée est ESC et que le focus est à l'intérieur de <input type="text" /> . Dans ce scénario, vous pouvez utiliser onKeyDown y onKeyUp qui tirent tous les deux, et dans le bon ordre.

5 votes

event.keyCode est déprécié, vous devez utiliser event.key qui renverra Escape quand Esc est en panne.

32voto

Jonas Sandstedt Points 126

Une autre façon d'accomplir ceci dans un composant fonctionnel, est d'utiliser useEffect comme ceci :

import React, { useEffect } from 'react';

const App = () => {

  useEffect(() => {
    const handleEsc = (event) => {
       if (event.keyCode === 27) {
        console.log('Close')
      }
    };
    window.addEventListener('keydown', handleEsc);

    return () => {
      window.removeEventListener('keydown', handleEsc);
    };
  }, []);

  return(<p>Press ESC to console log "Close"</p>);
}

Au lieu de console.log, vous pouvez utiliser useState pour déclencher quelque chose.

0 votes

Quel est le type de texte utilisé ici pour event ?

0 votes

Je n'utilise pas de texte dactylographié, donc je ne sais pas. Mais c'est juste un rappel d'événement standard du navigateur. Je suppose que typescript a une documentation que vous pouvez consulter.

2 votes

Le type d'événement est KeyboardEvent . De même, au lieu d'utiliser event.keyCode il convient d'utiliser event.key puisque keyCode es obsolète .

20voto

Bjorn Reppen Points 5009

Pour une solution de crochet React réutilisable

import React, { useEffect } from 'react';

const useEscape = (onEscape) => {
    useEffect(() => {
        const handleEsc = (event) => {
            if (event.keyCode === 27) 
                onEscape();
        };
        window.addEventListener('keydown', handleEsc);

        return () => {
            window.removeEventListener('keydown', handleEsc);
        };
    }, []);
}

export default useEscape

Uso:

const [isOpen, setIsOpen] = useState(false);
useEscape(() => setIsOpen(false))

5 votes

La solution ne permet pas de modifier la fonction onEscape. Vous devez utiliserMemo et passer onEscape comme tableau dep pour useEffect.

1 votes

@Neo pouvez-vous préciser ?

0 votes

Si vous changez la propriété onEscape en quelque chose d'autre après le chargement, il continuera à appeler le onEscape original. Cependant, il s'agit d'un cas d'utilisation très inhabituel, à moins que vous n'écriviez une bibliothèque, donc moi-même je ne m'embêterais pas à ajouter cette complexité à moins que j'en aie besoin.

13voto

BitOfUniverse Points 2516

React utilise SyntheticKeyboardEvent pour envelopper l'évènement natif du navigateur et cet évènement synthétique fournit attribut clé nommé ,
que vous pouvez utiliser comme ceci :

handleOnKeyDown = (e) => {
  if (['Enter', 'ArrowRight', 'Tab'].includes(e.key)) {
    // select item
    e.preventDefault();
  } else if (e.key === 'ArrowUp') {
    // go to top item
    e.preventDefault();
  } else if (e.key === 'ArrowDown') {
    // go to bottom item
    e.preventDefault();
  } else if (e.key === 'Escape') {
    // escape
    e.preventDefault();
  }
};

3 votes

Fun fact si vous devez prendre en charge IE9 et/ou Firefox 36 ou moins, e.key pour Escape revient en tant que Esc #triggered

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