Chcę powiązać, aby zamknąć aktywne okno wyskakujące bootstrap reagowania na escape
prasie. Oto kod
_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);
},
Ale nic się nie loguje w konsoli po naciśnięciu dowolnego klawisza. Próbowałem słuchać tego również w oknie iz różnymi przypadkami. „Keypress”, „keyup” itp., Ale wygląda na to, że robię coś nie tak.
reactjs
react-jsx
react-bootstrap
zawsze się ucz
źródło
źródło
Odpowiedzi:
Powinieneś używać,
keydown
a niekeypress
.Keypress (przestarzałe) jest zwykle używane tylko w przypadku klawiszy, które generują znak wyjściowy zgodnie z dokumentacją
Keypress (przestarzałe)
Keydown
źródło
Sam miałem z tym podobny problem. Użyję twojego kodu, aby zilustrować poprawkę.
// 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); },
Ponieważ używasz metody createClass do robienia rzeczy, nie musisz wiązać się z pewnymi metodami, co
this
jest niejawne w każdej zdefiniowanej metodzie.Istnieje działające jsfiddle, wykorzystujące metodę createClass do tworzenia komponentów React .
źródło
componentWillMount
w React 16.3 jest przestarzałe. IMO powinieneś zamiast tego zarejestrować detektory zdarzeń wcomponentDidMount
.Jeśli możesz używać haków React, dobrym podejściem jest to
useEffect
, aby nasłuchiwacz zdarzeń był subskrybowany tylko raz i poprawnie anulowany, gdy komponent zostanie odmontowany.Poniższy przykład został wyodrębniony z https://usehooks.com/useEventListener/ :
// 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 ); };
Można go też zainstalować npm z npm
npm i @use-it/event-listener
- zobacz projekt tutaj - https://github.com/donavon/use-event-listener .Następnie, aby użyć go w swoim komponencie, wystarczy wywołać go wewnątrz komponentu funkcjonalnego, przekazując nazwę zdarzenia i procedurę obsługi. Na przykład, jeśli chcesz za
console.log
każdym razem, gdy naciśniesz klawisz Escape: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>; }
źródło
ref
" jest naprawdę kluczowy - nie przekazuj swoich programów obsługi zdarzeń douseEffect
tablicy zależności, do której je dodajedocument.body.onKeyDown
!Wersja odpowiedzi Jt oso, która jest bardziej odpowiednia dla tego pytania. Myślę, że jest to znacznie prostsze niż inne odpowiedzi, które używają zewnętrznych bibliotek lub haków API do łączenia / usuwania wiązania słuchacza.
var KEY_ESCAPE = 27; ... function handleKeyDown(event) { if (event.keyCode === KEY_ESCAPE) { /* do your action here */ } } ... <div onKeyDown={handleKeyDown}> ...
źródło
if (event.key === 'Escape')
Miałem te same wymagania co do elementu div, który można zakładać.
Poniższy kod znajdował się w wywołaniu items.map ((item) => ...
<div tabindex="0" onClick={()=> update(item.id)} onKeyDown={()=> update(item.id)} > {renderItem(item)} </div>
To zadziałało dla mnie!
źródło
Chciałem mieć globalnych odbiorników wydarzeń i miałem dziwne zachowanie z powodu korzystania z portali reagujących. Zdarzenie było nadal wyzwalane w elemencie dokumentu, mimo że zostało anulowane w module modalnym portalu w dokumencie.
Zacząłem używać tylko detektorów zdarzeń na obiekcie głównym, który otacza całe drzewo komponentów. Problem polegał na tym, że początkowo skupiono się na treści, a nie na elemencie głównym, dlatego zdarzenia byłyby najpierw uruchamiane, gdy skupisz się na elemencie w drzewie.
Rozwiązaniem, które wybrałem, jest dodanie tabindeksu i automatyczne ustawienie go za pomocą haka efektu.
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> };
źródło