Я хочу привязать, чтобы закрыть всплывающее окно загрузки активного ответа при escape
нажатии. Вот код
_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);
},
Но при нажатии любой клавиши в консоли ничего не происходит. Я также пытался прослушать это в окне и в разных случаях. 'Keypress', 'keyup' и т. Д., Но похоже, что я делаю что-то не так.
reactjs
react-jsx
react-bootstrap
всегда учиться
источник
источник
Ответы:
Вы должны использовать
keydown
и нетkeypress
.Нажатие клавиши (устарело) обычно используется только для клавиш, которые производят символьный вывод в соответствии с документами
Keypress (устарело)
Keydown
источник
У меня была аналогичная проблема с этим. Я буду использовать ваш код, чтобы проиллюстрировать исправление.
// 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); },
Поскольку вы используете способ createClass, вам не нужно привязываться к определенным методам, как
this
это подразумевается в каждом определенном методе.Здесь есть рабочий jsfiddle, использующий метод createClass для создания компонента React .
источник
componentWillMount
это устарело с React 16.3. ИМО вам следует вместо этого зарегистрировать слушателей событийcomponentDidMount
.Если вы можете использовать React Hooks, то это будет хороший подход
useEffect
, чтобы прослушиватель событий был подписан только один раз и правильно отписался, когда компонент отключен.Пример ниже был извлечен из 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 ); };
Вы также можете установить его, например, из npm
npm i @use-it/event-listener
- см. Проект здесь - https://github.com/donavon/use-event-listener .Затем, чтобы использовать его в своем компоненте, вам просто нужно вызвать его внутри своего функционального компонента, передав имя события и обработчик. Например, если вы хотите
console.log
каждый раз нажимать клавишу 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>; }
источник
ref
» действительно является ключевым - не передавайте обработчики событий вuseEffect
массив зависимостей, в который они добавляютсяdocument.body.onKeyDown
!Версия ответа Jt oso, более подходящая для этого вопроса. Я думаю, что это намного проще, чем другие ответы, в которых используются внешние библиотеки или перехватчики API для привязки / отмены привязки слушателя.
var KEY_ESCAPE = 27; ... function handleKeyDown(event) { if (event.keyCode === KEY_ESCAPE) { /* do your action here */ } } ... <div onKeyDown={handleKeyDown}> ...
источник
if (event.key === 'Escape')
У меня были те же требования к div с вкладками.
Следующий код для меня был внутри вызова items.map ((item) => ...
<div tabindex="0" onClick={()=> update(item.id)} onKeyDown={()=> update(item.id)} > {renderItem(item)} </div>
Это сработало для меня!
источник
Я хотел иметь глобальные прослушиватели событий, и у меня было странное поведение из-за использования React Portals. Событие все еще было инициировано для элемента документа, несмотря на то, что оно было отменено для модального компонента портала в документе.
Я перешел к использованию прослушивателей событий только для корневого объекта, который охватывает все дерево компонентов. Проблема заключалась в том, что изначально сфокусировано тело, а не корневой элемент, поэтому события сначала запускались, как только вы фокусируете элемент в дереве.
Решение, которое я выбрал, - это добавить tabindex и автоматически сфокусировать его с помощью хука эффекта.
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> };
источник