Ich möchte binden, um das aktive React-Bootstrap-Popover beim escape
Drücken zu schließen. Hier ist der Code
_handleEscKey:function(event){
console.log(event);
if(event.keyCode == 27){
this.state.activePopover.hide();
}
},
componentWillMount:function(){
BannerDataStore.addChangeListener(this._onchange);
document.addEventListener("click", this._handleDocumentClick, false);
document.addEventListener("keyPress", this._handleEscKey, false);
},
componentWillUnmount: function() {
BannerDataStore.removeChangeListener(this._onchange);
document.removeEventListener("click", this._handleDocumentClick, false);
document.removeEventListener("keyPress", this._handleEscKey, false);
},
Es wird jedoch nichts in der Konsole protokolliert, wenn ich eine Taste drücke. Ich habe versucht, das auch im Fenster und in verschiedenen Fällen zu hören. "Tastendruck", "Tastendruck" usw., aber es scheint, dass ich etwas falsch mache.
reactjs
react-jsx
react-bootstrap
immer lernen
quelle
quelle
Antworten:
Sie sollten verwenden
keydown
und nichtkeypress
.Tastendruck (veraltet) wird normalerweise nur für Tasten verwendet, die eine Zeichenausgabe gemäß den Dokumenten erzeugen
Tastendruck (veraltet)
Taste nach unten
quelle
Hatte gerade ein ähnliches Problem damit. Ich werde Ihren Code verwenden, um eine Korrektur zu veranschaulichen.
// for other devs who might not know keyCodes var ESCAPE_KEY = 27; _handleKeyDown = (event) => { switch( event.keyCode ) { case ESCAPE_KEY: this.state.activePopover.hide(); break; default: break; } }, // componentWillMount deprecated in React 16.3 componentDidMount(){ BannerDataStore.addChangeListener(this._onchange); document.addEventListener("click", this._handleDocumentClick, false); document.addEventListener("keydown", this._handleKeyDown); }, componentWillUnmount() { BannerDataStore.removeChangeListener(this._onchange); document.removeEventListener("click", this._handleDocumentClick, false); document.removeEventListener("keydown", this._handleKeyDown); },
Da Sie die Methode createClass verwenden, müssen Sie nicht an bestimmte Methoden binden, wie dies
this
in jeder definierten Methode impliziert ist.Es gibt eine funktionierende jsfiddle, die hier die createClass-Methode zur Erstellung von React-Komponenten verwendet .
quelle
componentWillMount
dies ab Reaktion 16.3 veraltet ist. IMO sollten Sie stattdessen die Ereignis-Listener registrierencomponentDidMount
.Wenn Sie React Hooks verwenden können, ist dies ein guter Ansatz
useEffect
, sodass der Ereignis-Listener nur einmal abonniert und ordnungsgemäß abgemeldet wird, wenn die Komponente nicht bereitgestellt wird.Das folgende Beispiel wurde aus https://usehooks.com/useEventListener/ extrahiert :
// Hook function useEventListener(eventName, handler, element = window){ // Create a ref that stores handler const savedHandler = useRef(); // Update ref.current value if handler changes. // This allows our effect below to always get latest handler ... // ... without us needing to pass it in effect deps array ... // ... and potentially cause effect to re-run every render. useEffect(() => { savedHandler.current = handler; }, [handler]); useEffect( () => { // Make sure element supports addEventListener // On const isSupported = element && element.addEventListener; if (!isSupported) return; // Create event listener that calls handler function stored in ref const eventListener = event => savedHandler.current(event); // Add event listener element.addEventListener(eventName, eventListener); // Remove event listener on cleanup return () => { element.removeEventListener(eventName, eventListener); }; }, [eventName, element] // Re-run if eventName or element changes ); };
Sie können es auch von npm aus installieren, z. B.
npm i @use-it/event-listener
- siehe Projekt hier - https://github.com/donavon/use-event-listener .Um es dann in Ihrer Komponente zu verwenden, müssen Sie es nur in Ihrer Funktionskomponente aufrufen und den Ereignisnamen und den Handler übergeben. Wenn Sie beispielsweise
console.log
jedes Mal möchten, wenn die Escape-Taste gedrückt wird:import useEventListener from '@use-it/event-listener' const ESCAPE_KEYS = ['27', 'Escape']; const App = () => { function handler({ key }) { if (ESCAPE_KEYS.includes(String(key))) { console.log('Escape key pressed!'); } } useEventListener('keydown', handler); return <span>hello world</span>; }
quelle
ref
Effekt "Listener für einen speichern " ist wirklich wichtig - übergeben Sie Ihre Ereignishandler nicht in demuseEffect
Abhängigkeitsarray, zu dem sie hinzugefügt werdendocument.body.onKeyDown
!Eine Version der Antwort von Jt oso, die für diese Frage relevanter ist. Ich denke, dies ist viel einfacher als die anderen Antworten, die externe Bibliotheken oder API-Hooks verwenden, um den Listener zu binden / zu lösen.
var KEY_ESCAPE = 27; ... function handleKeyDown(event) { if (event.keyCode === KEY_ESCAPE) { /* do your action here */ } } ... <div onKeyDown={handleKeyDown}> ...
quelle
Ich hatte die gleichen Anforderungen für ein Div, das tabulatorfähig war.
Der folgende Code war für mich Teil eines Aufrufs von items.map ((item) => ...
<div tabindex="0" onClick={()=> update(item.id)} onKeyDown={()=> update(item.id)} > {renderItem(item)} </div>
Das hat bei mir funktioniert!
quelle
Ich wollte globale Ereignis-Listener haben und hatte aufgrund der Verwendung von React Portals ein seltsames Verhalten. Das Ereignis wurde weiterhin für das Dokumentelement ausgelöst, obwohl es für eine modale Portalkomponente im Dokument abgebrochen wurde.
Ich habe nur Ereignis-Listener für ein Stammobjekt verwendet, das den gesamten Komponentenbaum umschließt. Das Problem hierbei war, dass anfangs der Körper fokussiert ist und nicht das Wurzelelement. Daher werden die Ereignisse zuerst ausgelöst, sobald Sie ein Element innerhalb des Baums fokussieren.
Die Lösung, für die ich mich entschieden habe, besteht darin, einen Tabindex hinzuzufügen und ihn automatisch mit einem Effekthaken zu fokussieren.
import React from "react"; export default GlobalEventContainer = ({ children, ...props }) => { const rootRef = React.useRef(null); useEffect(() => { if (document.activeElement === document.body && rootContainer.current) rootContainer.current.focus(); } }); return <div {...props} tabIndex="0" ref={rootRef}>{children}</div> };
quelle