react-hotkeys
react-hotkeys copied to clipboard
keybindings break on re-render
I am really excited about this new version - using integrated react events should solve a lot of head aches and workarounds I'm having right now.
I am trying the new version, and I don't always get key triggers. I think this is because my component re-renders when I click on it.
It definitely gets worse when I set onFocus={}
Expected behavior Hot keys matches should always trigger action, when hot key element is focused.
Platform (please complete the following information):
- version: 2.0.0
- chrome
- OS: MacOS Mojave
Code to reproduce:
import React, { useState } from "react";
import { HotKeys,configure } from "react-hotkeys";
export function App() {
const [state, setState] = useState(1);
return (
<div className="App">
<div>{state}</div>
<SubApp state={state} setState={setState} />
</div>
);
};
function SubApp({ state, setState }) {
const go = e => {
console.log("GO", state, 'key:', e.key);
setState(state + 1);
};
return (
<HotKeys
keyMap={{ GO: "enter" }}
handlers={{ GO: go }}
allowChanges={true}
//makes things worse:
// onFocus={() => console.log("onFocus")}
>
hello! {state}
</HotKeys>
);
}
adding log:
HotKeys (F0📕-E0❤️-C0🔺) Registered component:
{
"childIds": [],
"parentId": null,
"keyMap": {
"GO": "enter"
}
}
AbstractKeyEventStrategy.js:351 HotKeys (F0📕-E0❤️-C0🔺) Registered component mount:
{
"childIds": [],
"parentId": null,
"keyMap": {
"GO": "enter"
}
}
FocusOnlyKeyEventStrategy.js:246 HotKeys (F0📕-C0🔺-P0🔺:) Focused.
FocusOnlyKeyEventStrategy.js:249 HotKeys (F0📕-C0🔺-P0🔺:) Component options:
{
"actions": {
"GO": [
{
"prefix": "",
"actionName": "GO",
"sequenceLength": 1,
"id": "Enter",
"keyDictionary": {
"Enter": true
},
"keyEventType": 0,
"size": 1
}
]
},
"handlers": {
"GO": "e => {\n console.log(\"GO\", state, 'key:', e.key);\n setState(state + 1);\n }"
},
"componentId": 0,
"options": {
"defaultKeyEvent": "keydown"
}
}
FocusOnlyKeyEventStrategy.js:391 HotKeys (F0📕-E1💚-C0🔺-P0🔺:) New 'Enter' keydown event.
FocusOnlyKeyEventStrategy.js:626 HotKeys (F0📕-E1💚-C0🔺-P0🔺:) Added 'Enter' to current combination: 'Enter'.
FocusOnlyKeyEventStrategy.js:631 HotKeys (F0📕-E1💚-C0🔺-P0🔺:) Key history: [
{
"keys": {
"Enter": [
[
0,
0,
0
],
[
1,
0,
0
]
]
},
"ids": [
"Enter"
],
"keyAliases": {}
}
].
FocusOnlyKeyEventStrategy.js:741 HotKeys (F0📕-E1💚-C0🔺-P0🔺:) Attempting to find action matching 'Enter' keydown . . .
AbstractKeyEventStrategy.js:451 HotKeys (F0📕-E1💚-C0🔺-P0🔺:) Internal key mapping:
{
"": {
"actionConfigs": {
"Enter": {
"prefix": "",
"sequenceLength": 1,
"id": "Enter",
"keyDictionary": {
"Enter": true
},
"size": 1,
"events": {
"0": {
"actionName": "GO",
"handler": "e => {\n console.log(\"GO\", state, 'key:', e.key);\n setState(state + 1);\n }"
}
}
}
},
"order": null
}
}
AbstractKeyEventStrategy.js:464 HotKeys (F0📕-E1💚-C0🔺-P0🔺:) Found action that matches 'Enter': GO. Calling handler . . .
App.js:23 GO 1 key: Enter
FocusOnlyKeyEventStrategy.js:601 HotKeys (F0📕-E1💚-C0🔺-P0🔺:) Stopping further event propagation.
FocusOnlyKeyEventStrategy.js:391 HotKeys (F0📕-E3💛-C0🔺-P0🔺:) New (simulated) 'Enter' keypress event.
FocusOnlyKeyEventStrategy.js:631 HotKeys (F0📕-E3💛-C0🔺-P0🔺:) Key history: [
{
"keys": {
"Enter": [
[
1,
0,
0
],
[
1,
2,
0
]
]
},
"ids": [
"Enter"
],
"keyAliases": {}
}
].
FocusOnlyKeyEventStrategy.js:730 HotKeys (F0📕-E3💛-C0🔺-P0🔺:) Ignored 'Enter' keypress because it doesn't have any keypress handlers.
FocusOnlyKeyEventStrategy.js:281 HotKeys (F0📕-C0🔺-P0🔺:) Received new props.
FocusOnlyKeyEventStrategy.js:291 HotKeys (F0📕-C0🔺-P0🔺:) Component options:
{
"actions": {
"GO": [
{
"prefix": "",
"actionName": "GO",
"sequenceLength": 1,
"id": "Enter",
"keyDictionary": {
"Enter": true
},
"keyEventType": 0,
"size": 1
}
]
},
"handlers": {
"GO": "e => {\n console.log(\"GO\", state, 'key:', e.key);\n setState(state + 1);\n }"
},
"componentId": 0,
"options": {
"defaultKeyEvent": "keydown"
}
}
FocusOnlyKeyEventStrategy.js:432 HotKeys (F0📕-E3💛-C0🔺-P0🔺:) Ignored 'Enter' keypress as it was not expected, and has already been simulated.
EventPropagator.js:268 HotKeys (F0📕-E3💛-Cnull🔺) Stopping further event propagation.
FocusOnlyKeyEventStrategy.js:313 HotKeys (F0📕-C0🔺-P0🔺:) Lost focus.
KeyEventManager.js:183 HotKeys: Window focused - clearing key history
FocusOnlyKeyEventStrategy.js:246 HotKeys (F1📗-C0🔺-P0🔺:) Focused.
FocusOnlyKeyEventStrategy.js:249 HotKeys (F1📗-C0🔺-P0🔺:) Component options:
{
"actions": {
"GO": [
{
"prefix": "",
"actionName": "GO",
"sequenceLength": 1,
"id": "Enter",
"keyDictionary": {
"Enter": true
},
"keyEventType": 0,
"size": 1
}
]
},
"handlers": {
"GO": "e => {\n console.log(\"GO\", state, 'key:', e.key);\n setState(state + 1);\n }"
},
"componentId": 0,
"options": {
"defaultKeyEvent": "keydown"
}
}
Hey @KutnerUri, it's fantastic to hear you're excited about the improvements v2 brings.
Thank you for including your logs, that is generally the most helpful thing people can do short of creating a demo of the problem.
Were these logs for an instance where an action trigger was missed? There appears to be nothing awry in them - the Enter
key seems to have been pressed once. The window is unfocused half way through the log - are you sure subsequent presses of the Enter
key aren't occurring when the window is out of focus?
Yes, I am sure. try it for yourself: https://codesandbox.io/embed/compassionate-maxwell-hxs8y
Running into this issue on an app I'm working on as well. What's really weird is this sequence:
- Trigger hotkey, causing rerender
- Hotkeys are broken
- Focus other application
- Refocus browser (without interacting with react application)
- Hotkeys work
Is there a fix to this? I'm experiencing the same problem.
The hotkeys work on mount but after the first render they break. I console logged it and it seems like the keyMap and handler props are resetting. I'm not sure if that's the the problem.
Has anyone found a workaround for this?
Running into this issue on an app I'm working on as well. What's really weird is this sequence:
- Trigger hotkey, causing rerender
- Hotkeys are broken
- Focus other application
- Refocus browser (without interacting with react application)
- Hotkeys work
I'm observing something very similar to what you are describing.
- click on input inside
<HotKeys?
- input some value, e.g. "a"
- press "enter"
Expect: The "enter" handler to trigger. Actual: The "enter" handler does not trigger.
Interestingly, if i skip step 2. i the "enter" handler does trigger.
My example is rather complicated. I have multiple GlobalHotKeys instances (that work as expected) in play in addition the HotKeys component that is giving me trouble.
I attempted to reproduce in a simpler example. I was not able to reproduce the behavior that I am seeing, but i did reproduce some behavior that i would think is a bug, and it may be connected.
https://codesandbox.io/s/react-hotkeys-r8xp8
Yes, I am sure. try it for yourself: https://codesandbox.io/embed/compassionate-maxwell-hxs8y
adding configure({ simulateMissingKeyPressEvents: false });
works around this issue .
Same for https://codesandbox.io/s/react-hotkeys-r8xp8.
This does cause problems though on my project when handling 2+ key sequences (eg IMAGE_ZOOM_OUT: 'alt+-'
) only working once you repress the held down key.
I was able to fix @KutnerUri's issue by bluring and refocusing document.activeElement
. Obviously a very hacky solution but could be a clue as to how to fix the underlying issue.
https://codesandbox.io/s/xenodochial-cherry-ikcr2?file=/src/index.js
I can reproduce this even if the app never re-renders. The handling stops working after pressing the enter key. It does not have to be defined in the keymap either. Although, it continues working when I call preventDefault
with an extra even handler on the enter key.
Edit: Seems fixed in the forked react-hotkeys-ce package.