Quiero enlazar para cerrar la escape
ventana emergente de arranque de reacción activa al presionar. Aquí está el código
_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);
},
Pero no se registra nada en la consola cuando presiono cualquier tecla. Intenté escuchar eso en la ventana también y con diferentes casos. 'Keypress', 'keyup', etc. pero parece que estoy haciendo algo mal.
reactjs
react-jsx
react-bootstrap
siempre aprender
fuente
fuente
Respuestas:
Deberías usar
keydown
y nokeypress
.La pulsación de teclas (obsoleta) se usa generalmente solo para teclas que producen una salida de caracteres según los documentos
Pulsación de tecla (obsoleta)
Keydown
fuente
Solo tuve un problema similar con esto yo mismo. Usaré su código para ilustrar una solución.
// 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); },
Dado que está utilizando la forma createClass de hacer las cosas, no necesita vincularse a ciertos métodos como
this
está implícito en cada método definido.Hay un jsfiddle en funcionamiento, usando el método createClass de creación del componente React aquí.
fuente
componentWillMount
ha quedado obsoleto a partir de React 16.3. En mi opinión, debería registrar los oyentes de eventos encomponentDidMount
.Si puede usar React Hooks, un buen enfoque es hacerlo
useEffect
, por lo que el detector de eventos se suscribirá solo una vez y se cancelará correctamente cuando se desmonte el componente.El siguiente ejemplo se extrajo de 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 ); };
También puede instalarlo desde npm, por ejemplo,
npm i @use-it/event-listener
- vea el proyecto aquí - https://github.com/donavon/use-event-listener .Luego, para usarlo en su componente solo tiene que llamarlo dentro de su componente funcional pasando el nombre del evento y el controlador. Por ejemplo, si lo desea
console.log
cada vez que se presiona la tecla 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>; }
fuente
ref
" es realmente clave: ¡no pase sus controladores de eventos en lauseEffect
matriz de dependencia que los agregadocument.body.onKeyDown
!Una versión de la respuesta de Jt oso que es más relevante para esta pregunta. Creo que esto es mucho más simple que las otras respuestas que usan bibliotecas externas o ganchos de API para vincular / desvincular al oyente.
var KEY_ESCAPE = 27; ... function handleKeyDown(event) { if (event.keyCode === KEY_ESCAPE) { /* do your action here */ } } ... <div onKeyDown={handleKeyDown}> ...
fuente
Tenía los mismos requisitos para un div que se podía tabular.
El siguiente código para mí estaba dentro de una llamada a items.map ((item) => ...
<div tabindex="0" onClick={()=> update(item.id)} onKeyDown={()=> update(item.id)} > {renderItem(item)} </div>
¡Esto funcionó para mí!
fuente
Quería tener oyentes de eventos globales y tuve un comportamiento extraño debido al uso de React Portals. El evento aún se desencadenó en el elemento del documento a pesar de que se canceló en un componente modal del portal dentro del documento.
Me moví hacia el uso solo de detectores de eventos en un objeto raíz que envuelve todo el árbol de componentes. El problema aquí era que inicialmente se enfoca el cuerpo y no el elemento raíz, por lo que los eventos se dispararían primero una vez que enfoca un elemento dentro del árbol.
La solución que elegí fue agregar un tabindex y enfocarlo automáticamente con un gancho de efecto.
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> };
fuente