Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Shift+Space combination doesn't work and breaks other bindings #300

Open
andrew-sv opened this issue Feb 8, 2021 · 1 comment
Open

Comments

@andrew-sv
Copy link

andrew-sv commented Feb 8, 2021

Describe the bug
Here is the link to sandbox where this bug can be reproduced: [https://codesandbox.io/s/happy-johnson-su7vz]
Steps to reproduce:

  1. Focus button and press Shift+Space
  2. It writes message to console "(Shift+Space) pressed"
  3. Press Shift+Space one more time. It doesn't output anything to console.
  4. Refocus element and try to press Shift without space. You can see "(Shift+Space) pressed" in console.
  5. Try to press another combination: Shift+R. It doesn't work.
  6. If you reload the page and try similar steps with Shift+R combination, everything will work fine.

How are you using react hotkeys components? (HotKeys, GlobalHotKeys, IgnoreKeys etc)

Expected behavior
Shift+Space combination should work properly.

Platform (please complete the following information):

  • react-hotkeys v2.0.0
  • Browser: chrome
  • OS: Windows

Are you willing and able to create a PR request to fix this issue?
Yes.

Include the smallest log that includes your issue:

HotKeys (C0🔺): Registered component in application key map:
 {
    "childIds": [],
    "parentId": null,
    "keyMap": {
        "ACTION1": "shift+space",
        "ACTION2": "shift+r"
    }
}
HotKeys (Fundefinedundefined-C0🔺): Registered component mount:
 {
    "childIds": [],
    "parentId": null,
    "keyMap": {
        "ACTION1": "shift+space",
        "ACTION2": "shift+r"
    }
}
HotKeys (Fundefinedundefined-C0🔺-P0🔺): Focused
HotKeys (Fundefinedundefined-C0🔺-P0🔺): New component options:
 {
    "actions": {
        "ACTION1": [
            {
                "prefix": "",
                "actionName": "ACTION1",
                "sequenceLength": 1,
                "id": "Shift+ ",
                "keyDictionary": {
                    "Shift": true,
                    " ": true
                },
                "keyEventType": 0,
                "size": 2
            }
        ],
        "ACTION2": [
            {
                "prefix": "",
                "actionName": "ACTION2",
                "sequenceLength": 1,
                "id": "Shift+r",
                "keyDictionary": {
                    "Shift": true,
                    "r": true
                },
                "keyEventType": 0,
                "size": 2
            }
        ]
    },
    "handlers": {
        "ACTION1": "spy",
        "ACTION2": "spy"
    },
    "componentId": 0,
    "options": {
        "defaultKeyEvent": "keydown"
    }
}
HotKeys (Fundefinedundefined-C0🔺-P0🔺-E1💚): New 'Shift' keydown event.
HotKeys (Fundefinedundefined-C0🔺-P0🔺-E1💚): Added 'Shift' to current combination: 'Shift'.
HotKeys (Fundefinedundefined-C0🔺-P0🔺-E1💚): Key history: [
    {
        "keys": {
            "Shift": [
                [
                    0,
                    0,
                    0
                ],
                [
                    1,
                    0,
                    0
                ]
            ]
        },
        "ids": [
            "Shift"
        ],
        "keyAliases": {}
    }
].
HotKeys (F0📕-C0🔺-P0🔺-E1💚): Attempting to find action matching 'Shift' keydown . . .
HotKeys (Fundefinedundefined-C0🔺-P0🔺-E1💚): Internal key mapping:
 {
    "": {
        "actionConfigs": {
            "Shift+ ": {
                "prefix": "",
                "sequenceLength": 1,
                "id": "Shift+ ",
                "keyDictionary": {
                    "Shift": true,
                    " ": true
                },
                "size": 2,
                "events": {
                    "0": {
                        "actionName": "ACTION1",
                        "handler": "spy"
                    }
                }
            },
            "Shift+r": {
                "prefix": "",
                "sequenceLength": 1,
                "id": "Shift+r",
                "keyDictionary": {
                    "Shift": true,
                    "r": true
                },
                "size": 2,
                "events": {
                    "0": {
                        "actionName": "ACTION2",
                        "handler": "spy"
                    }
                }
            }
        },
        "order": null
    }
}
HotKeys (Fundefinedundefined-C0🔺-P0🔺-E1💚): No matching actions found for 'Shift' keydown.
HotKeys (Fundefinedundefined-C0🔺-P0🔺-E3💛): New (simulated) 'Shift' keypress event.
HotKeys (Fundefinedundefined-C0🔺-P0🔺-E3💛): Key history: [
    {
        "keys": {
            "Shift": [
                [
                    1,
                    0,
                    0
                ],
                [
                    1,
                    2,
                    0
                ]
            ]
        },
        "ids": [
            "Shift"
        ],
        "keyAliases": {}
    }
].
HotKeys (Fundefinedundefined-C0🔺-P0🔺-E3💛): Ignored 'Shift' keypress because it doesn't have any keypress handlers.
HotKeys (Fundefinedundefined-C0🔺-P0🔺-E4💜): New ' ' keydown event.
HotKeys (Fundefinedundefined-C0🔺-P0🔺-E4💜): Added ' ' to current combination: 'Shift+ '.
HotKeys (Fundefinedundefined-C0🔺-P0🔺-E4💜): Key history: [
    {
        "keys": {
            "Shift": [
                [
                    1,
                    0,
                    0
                ],
                [
                    1,
                    2,
                    0
                ]
            ],
            " ": [
                [
                    0,
                    0,
                    0
                ],
                [
                    1,
                    0,
                    0
                ]
            ]
        },
        "ids": [
            "Shift+ "
        ],
        "keyAliases": {}
    }
].
HotKeys (F0📕-C0🔺-P0🔺-E4💜): Attempting to find action matching 'Shift+ ' keydown . . .
HotKeys (Fundefinedundefined-C0🔺-P0🔺-E4💜): Internal key mapping:
 {
    "": {
        "actionConfigs": {
            "Shift+ ": {
                "prefix": "",
                "sequenceLength": 1,
                "id": "Shift+ ",
                "keyDictionary": {
                    "Shift": true,
                    " ": true
                },
                "size": 2,
                "events": {
                    "0": {
                        "actionName": "ACTION1",
                        "handler": "spy"
                    }
                }
            },
            "Shift+r": {
                "prefix": "",
                "sequenceLength": 1,
                "id": "Shift+r",
                "keyDictionary": {
                    "Shift": true,
                    "r": true
                },
                "size": 2,
                "events": {
                    "0": {
                        "actionName": "ACTION2",
                        "handler": "spy"
                    }
                }
            }
        },
        "order": [
            "Shift+ ",
            "Shift+r"
        ]
    }
}
HotKeys (Fundefinedundefined-C0🔺-P0🔺-E4💜): Found action that matches 'Shift+ ': ACTION1. Calling handler . . .
HotKeys (Fundefinedundefined-C0🔺-P0🔺-E4💜): Stopping further event propagation.
HotKeys (Fundefinedundefined-C0🔺-P0🔺-E6❤️): New (simulated) ' ' keypress event.
HotKeys (Fundefinedundefined-C0🔺-P0🔺-E6❤️): Key history: [
    {
        "keys": {
            "Shift": [
                [
                    1,
                    0,
                    0
                ],
                [
                    1,
                    2,
                    0
                ]
            ],
            " ": [
                [
                    1,
                    0,
                    0
                ],
                [
                    1,
                    2,
                    0
                ]
            ]
        },
        "ids": [
            "Shift+ "
        ],
        "keyAliases": {}
    }
].
HotKeys (Fundefinedundefined-C0🔺-P0🔺-E6❤️): Ignored 'Shift+ ' keypress because it doesn't have any keypress handlers.
HotKeys (F0📕-C0🔺-P0🔺-E6❤️): Lost focus.
HotKeys (Fundefinedundefined-C0🔺-P0🔺): Focused
HotKeys (Fundefinedundefined-C0🔺-P0🔺): New component options:
 {
    "actions": {
        "ACTION1": [
            {
                "prefix": "",
                "actionName": "ACTION1",
                "sequenceLength": 1,
                "id": "Shift+ ",
                "keyDictionary": {
                    "Shift": true,
                    " ": true
                },
                "keyEventType": 0,
                "size": 2
            }
        ],
        "ACTION2": [
            {
                "prefix": "",
                "actionName": "ACTION2",
                "sequenceLength": 1,
                "id": "Shift+r",
                "keyDictionary": {
                    "Shift": true,
                    "r": true
                },
                "keyEventType": 0,
                "size": 2
            }
        ]
    },
    "handlers": {
        "ACTION1": "handler",
        "ACTION2": "spy"
    },
    "componentId": 0,
    "options": {
        "defaultKeyEvent": "keydown"
    }
}
HotKeys (Fundefinedundefined-C0🔺-P0🔺-E7💚): New 'Shift' keydown event.
HotKeys (Fundefinedundefined-C0🔺-P0🔺-E7💚): Started a new combination with 'Shift'.
HotKeys (Fundefinedundefined-C0🔺-P0🔺-E7💚): Key history: [
    {
        "keys": {
            "Shift": [
                [
                    1,
                    0,
                    0
                ],
                [
                    1,
                    2,
                    0
                ]
            ],
            " ": [
                [
                    1,
                    0,
                    0
                ],
                [
                    1,
                    2,
                    0
                ]
            ]
        },
        "ids": [
            "Shift+ "
        ],
        "keyAliases": {}
    },
    {
        "keys": {
            "Shift": [
                [
                    0,
                    0,
                    0
                ],
                [
                    1,
                    0,
                    0
                ]
            ],
            " ": [
                [
                    1,
                    0,
                    0
                ],
                [
                    1,
                    2,
                    0
                ]
            ]
        },
        "ids": [
            "Shift+ "
        ],
        "keyAliases": {}
    }
].
HotKeys (F1📗-C0🔺-P0🔺-E7💚): Attempting to find action matching 'Shift+ ' keydown . . .
HotKeys (Fundefinedundefined-C0🔺-P0🔺-E7💚): Internal key mapping:
 {
    "": {
        "actionConfigs": {
            "Shift+ ": {
                "prefix": "",
                "sequenceLength": 1,
                "id": "Shift+ ",
                "keyDictionary": {
                    "Shift": true,
                    " ": true
                },
                "size": 2,
                "events": {
                    "0": {
                        "actionName": "ACTION1",
                        "handler": "handler"
                    }
                }
            },
            "Shift+r": {
                "prefix": "",
                "sequenceLength": 1,
                "id": "Shift+r",
                "keyDictionary": {
                    "Shift": true,
                    "r": true
                },
                "size": 2,
                "events": {
                    "0": {
                        "actionName": "ACTION2",
                        "handler": "spy"
                    }
                }
            }
        },
        "order": null
    }
}
HotKeys (Fundefinedundefined-C0🔺-P0🔺-E7💚): Found action that matches 'Shift+ ': ACTION1. Calling handler . . .
HotKeys (Fundefinedundefined-C0🔺-P0🔺-E7💚): Stopping further event propagation.
HotKeys (Fundefinedundefined-C0🔺-P0🔺-E9💛): New (simulated) 'Shift' keypress event.
HotKeys (Fundefinedundefined-C0🔺-P0🔺-E9💛): Key history: [
    {
        "keys": {
            "Shift": [
                [
                    1,
                    0,
                    0
                ],
                [
                    1,
                    2,
                    0
                ]
            ],
            " ": [
                [
                    1,
                    0,
                    0
                ],
                [
                    1,
                    2,
                    0
                ]
            ]
        },
        "ids": [
            "Shift+ "
        ],
        "keyAliases": {}
    },
    {
        "keys": {
            "Shift": [
                [
                    1,
                    0,
                    0
                ],
                [
                    1,
                    2,
                    0
                ]
            ],
            " ": [
                [
                    1,
                    0,
                    0
                ],
                [
                    1,
                    2,
                    0
                ]
            ]
        },
        "ids": [
            "Shift+ "
        ],
        "keyAliases": {}
    }
].
HotKeys (Fundefinedundefined-C0🔺-P0🔺-E9💛): Ignored 'Shift+ ' keypress because it doesn't have any keypress handlers.
HotKeys (Fundefinedundefined-C0🔺-P0🔺-E10💜): New 'Shift' keyup event.
HotKeys (Fundefinedundefined-C0🔺-P0🔺-E10💜): Key history: [
    {
        "keys": {
            "Shift": [
                [
                    1,
                    0,
                    0
                ],
                [
                    1,
                    2,
                    0
                ]
            ],
            " ": [
                [
                    1,
                    0,
                    0
                ],
                [
                    1,
                    2,
                    0
                ]
            ]
        },
        "ids": [
            "Shift+ "
        ],
        "keyAliases": {}
    },
    {
        "keys": {
            "Shift": [
                [
                    1,
                    2,
                    0
                ],
                [
                    1,
                    2,
                    1
                ]
            ],
            " ": [
                [
                    1,
                    0,
                    0
                ],
                [
                    1,
                    2,
                    0
                ]
            ]
        },
        "ids": [
            "Shift+ "
        ],
        "keyAliases": {}
    }
].
HotKeys (Fundefinedundefined-C0🔺-P0🔺-E10💜): Ignored 'Shift+ ' keyup because it doesn't have any keyup handlers.

expected handler to have been called exactly once, but it was called twice
    handler([SyntheticEvent] {
  _dispatchInstances: null,
  _dispatchListeners: null,
  _targetInst: [FiberNode] {
    _debugHookTypes: null,
    _debugID: 138,
    _debugIsCurrentlyTiming: false,
    _debugNeedsRemount: false,
    _debugOwner: null,
    _debugSource: null,
    actualDuration: 0,
    actualStartTime: -1,
    alternate: null,
    child: null,
    childExpirationTime: 0,
    dependencies: null,
    effectTag: 0,
    elementType: "div",
    expirationTime: 0,
    firstEffect: null,
    index: 0,
    key: null,
    lastEffect: null,
    memoizedProps: { className: "childElement" },
    memoizedState: null,
    mode: 0,
    nextEffect: null,
    pendingProps: [Circular],
    ref: null,
    return: [FiberNode] {
      _debugHookTypes: null,
      _debugID: 136,
      _debugIsCurrentlyTiming: false,
      _debugNeedsRemount: false,
      _debugOwner: [FiberNode] {
        _debugHookTypes: null,
        _debugID: 134,
        _debugIsCurrentlyTiming: false,
        _debugNeedsRemount: false,
        _debugOwner: [FiberNode] {
          _debugHookTypes: null,
          _debugID: 130,
          _debugIsCurrentlyTiming: false,
          _debugNeedsRemount: false,
          _debugOwner: [FiberNode] {
            _debugHookTypes: null,
            _debugID: 128,
            _debugIsCurrentlyTiming: false,
            _debugNeedsRemount: false,
            _debugOwner: null,
            _debugSource: null,
            actualDuration: 0,
            actualStartTime: -1,
            alternate: null,
            child: [Circular],
            childExpirationTime: 0,
            dependencies: null,
            effectTag: 1,
            elementType: function WrapperComponent() {},
            expirationTime: 0,
            firstEffect: [Circular],
            index: 0,
            key: null,
            lastEffect: [Circular],
            memoizedProps: {
              Component: function HotKeysEnabled() {},
              context: null,
              props: {
                children: {
                  $$typeof: Symbol(react.element),
                  _owner: null,
                  _store: {  },
                  key: null,
                  props: [Circular],
                  ref: null,
                  type: "div"
                },
                handlers: { ACTION1: function spy() {}, ACTION2: function spy() {} },
                keyMap: { ACTION1: "shift+space", ACTION2: "shift+r" }
              },
              refProp: null,
              wrappingComponentProps: null
            },
            memoizedState: {
              context: null,
              mount: true,
              props: [Circular],
              wrappingComponentProps: null
            },
            mode: 0,
            nextEffect: null,
            pendingProps: [Circular],
            ref: null,
            return: [FiberNode] {
              _debugHookTypes: null,
              _debugID: 125,
              _debugIsCurrentlyTiming: false,
              _debugNeedsRemount: false,
              _debugOwner: null,
              _debugSource: null,
              actualDuration: 0,
              actualStartTime: -1,
              alternate: [FiberNode] {
                _debugHookTypes: null,
                _debugID: 125,
                _debugIsCurrentlyTiming: false,
                _debugNeedsRemount: false,
                _debugOwner: null,
                _debugSource: null,
                actualDuration: 0,
                actualStartTime: -1,
                alternate: [Circular],
                child: null,
                childExpirationTime: 0,
                dependencies: null,
                effectTag: 0,
                elementType: null,
                expirationTime: 1073741823,
                firstEffect: null,
                index: 0,
                key: null,
                lastEffect: null,
                memoizedProps: null,
                memoizedState: null,
                mode: 0,
                nextEffect: null,
                pendingProps: null,
                ref: null,
                return: null,
                selfBaseDuration: 0,
                sibling: null,
                stateNode: [FiberRootNode] {
                  callbackExpirationTime: 0,
                  callbackNode: null,
                  callbackPriority: 90,
                  containerInfo: <div><div tabindex="-1"><[...]</div>,
                  context: {  },
                  current: [Circular],
                  finishedExpirationTime: 0,
                  finishedWork: null,
                  firstPendingTime: 0,
                  firstSuspendedTime: 0,
                  hydrate: false,
                  interactionThreadID: 17,
                  lastExpiredTime: 0,
                  lastPingedTime: 0,
                  lastSuspendedTime: 0,
                  memoizedInteractions: Set {},
                  nextKnownPendingLevel: 0,
                  pendingChildren: null,
                  pendingContext: null,
                  pendingInteractionMap: [Map] {  },
                  pingCache: null,
                  tag: 0,
                  timeoutHandle: -1
                },
                tag: 3,
                treeBaseDuration: 0,
                type: null,
                updateQueue: {
                  baseQueue: {
                    callback: null,
                    expirationTime: 1073741823,
                    next: [Circular],
                    payload: {
                      element: {
                        $$typeof: Symbol(react.element),
                        _owner: null,
                        _store: {  },
                        key: null,
                        props: [Circular],
                        ref: null,
                        type: function WrapperComponent() {}
                      }
                    },
                    priority: 97,
                    suspenseConfig: null,
                    tag: 0
                  },
                  baseState: null,
                  effects: null,
                  shared: { pending: null }
                }
              },
              child: [Circular],
              childExpirationTime: 0,
              dependencies: null,
              effectTag: 0,
              elementType: null,
              expirationTime: 0,
              firstEffect: [Circular],
              index: 0,
              key: null,
              lastEffect: [Circular],
              memoizedProps: null,
              memoizedState: { element: [Circular] },
              mode: 0,
              nextEffect: null,
              pendingProps: null,
              ref: null,
              return: null,
              selfBaseDuration: 0,
              sibling: null,
              stateNode: [Circular],
              tag: 3,
              treeBaseDuration: 0,
              type: null,
              updateQueue: {
                baseQueue: null,
                baseState: [Circular],
                effects: null,
                shared: [Circular]
              }
            },
            selfBaseDuration: 0,
            sibling: null,
            stateNode: [WrapperComponent] {
              _reactInternalFiber: [Circular],
              _reactInternalInstance: {  },
              context: [Circular],
              props: [Circular],
              refs: {  },
              state: [Circular],
              updater: {
                enqueueForceUpdate: function enqueueForceUpdate() {},
                enqueueReplaceState: function enqueueReplaceState() {},
                enqueueSetState: function enqueueSetState() {},
                isMounted: function isMounted() {}
              }
            },
            tag: 1,
            treeBaseDuration: 0,
            type: function WrapperComponent() {},
            updateQueue: {
              baseQueue: null,
              baseState: [Circular],
              effects: null,
              shared: { pending: null }
            }
          },
          _debugSource: null,
          actualDuration: 0,
          actualStartTime: -1,
          alternate: null,
          child: [FiberNode] {
            _debugHookTypes: null,
            _debugID: 132,
            _debugIsCurrentlyTiming: false,
            _debugNeedsRemount: false,
            _debugOwner: [Circular],
            _debugSource: null,
            actualDuration: 0,
            actualStartTime: -1,
            alternate: null,
            child: [Circular],
            childExpirationTime: 0,
            dependencies: null,
            effectTag: 0,
            elementType: {
              $$typeof: Symbol(react.provider),
              _context: {
                $$typeof: Symbol(react.context),
                Consumer: {
                  $$typeof: Symbol(react.context),
                  _calculateChangedBits: null,
                  _context: [Circular]
                },
                Provider: [Circular],
                _calculateChangedBits: null,
                _currentRenderer: {  },
                _currentRenderer2: null,
                _currentValue: { hotKeysParentId: undefined },
                _currentValue2: [Circular],
                _threadCount: 0
              }
            },
            expirationTime: 0,
            firstEffect: null,
            index: 0,
            key: null,
            lastEffect: null,
            memoizedProps: {
              children: {
                $$typeof: Symbol(react.element),
                _owner: [Circular],
                _store: {  },
                key: null,
                props: {
                  children: [Circular],
                  hotKeys: {
                    onBlur: function () {},
                    onFocus: function () {},
                    onKeyDown: function () {},
                    onKeyPress: function () {},
                    onKeyUp: function () {},
                    tabIndex: "-1"
                  }
                },
                ref: null,
                type: function HotKeysWrapper() {}
              },
              value: { hotKeysParentId: 0 }
            },
            memoizedState: null,
            mode: 0,
            nextEffect: null,
            pendingProps: [Circular],
            ref: null,
            return: [Circular],
            selfBaseDuration: 0,
            sibling: null,
            stateNode: null,
            tag: 10,
            treeBaseDuration: 0,
            type: [Circular],
            updateQueue: null
          },
          childExpirationTime: 0,
          dependencies: {
            expirationTime: 0,
            firstContext: { context: [Circular], next: null, observedBits: 1073741823 },
            responders: null
          },
          effectTag: 5,
          elementType: function HotKeysEnabled() {},
          expirationTime: 0,
          firstEffect: null,
          index: 0,
          key: null,
          lastEffect: null,
          memoizedProps: { children: [Circular], handlers: [Circular], keyMap: [Circular] },
          memoizedState: null,
          mode: 0,
          nextEffect: null,
          pendingProps: [Circular],
          ref: null,
          return: [Circular],
          selfBaseDuration: 0,
          sibling: null,
          stateNode: [HotKeysEnabled] {
            _manager: [FocusOnlyComponentManager] {
              _focusTreeIds: [1],
              _focused: true,
              _hotKeysOptions: {  },
              childContext: [Circular],
              id: 0
            },
            _reactInternalFiber: [Circular],
            _reactInternalInstance: [Circular],
            context: [Circular],
            props: [Circular],
            refs: [Circular],
            state: null,
            updater: [Circular]
          },
          tag: 1,
          treeBaseDuration: 0,
          type: function HotKeysEnabled() {},
          updateQueue: {
            baseQueue: null,
            baseState: null,
            effects: null,
            shared: { pending: null }
          }
        },
        _debugSource: null,
        actualDuration: 0,
        actualStartTime: -1,
        alternate: null,
        child: [Circular],
        childExpirationTime: 0,
        dependencies: null,
        effectTag: 1,
        elementType: function HotKeysWrapper() {},
        expirationTime: 0,
        firstEffect: null,
        index: 0,
        key: null,
        lastEffect: null,
        memoizedProps: [Circular],
        memoizedState: null,
        mode: 0,
        nextEffect: null,
        pendingProps: [Circular],
        ref: null,
        return: [Circular],
        selfBaseDuration: 0,
        sibling: null,
        stateNode: [HotKeysWrapper] {
          _reactInternalFiber: [Circular],
          _reactInternalInstance: [Circular],
          context: [Circular],
          props: [Circular],
          refs: [Circular],
          state: null,
          updater: [Circular]
        },
        tag: 1,
        treeBaseDuration: 0,
        type: function HotKeysWrapper() {},
        updateQueue: { baseQueue: null, baseState: null, effects: null, shared: { pending: null } }
      },
      _debugSource: null,
      actualDuration: 0,
      actualStartTime: -1,
      alternate: null,
      child: [Circular],
      childExpirationTime: 0,
      dependencies: null,
      effectTag: 0,
      elementType: "div",
      expirationTime: 0,
      firstEffect: null,
      index: 0,
      key: null,
      lastEffect: null,
      memoizedProps: {
        children: [Circular],
        onBlur: function () {},
        onFocus: function () {},
        onKeyDown: function () {},
        onKeyPress: function () {},
        onKeyUp: function () {},
        tabIndex: "-1"
      },
      memoizedState: null,
      mode: 0,
      nextEffect: null,
      pendingProps: [Circular],
      ref: null,
      return: [Circular],
      selfBaseDuration: 0,
      sibling: null,
      stateNode: <div tabindex="-1"><div class="childEle[...]</div>,
      tag: 5,
      treeBaseDuration: 0,
      type: "div",
      updateQueue: null
    },
    selfBaseDuration: 0,
    sibling: null,
    stateNode: <div class="childElement"></div>,
    tag: 5,
    treeBaseDuration: 0,
    type: "div",
    updateQueue: null
  },
  bubbles: undefined,
  cancelable: undefined,
  currentTarget: null,
  defaultPrevented: undefined,
  dispatchConfig: {
    dependencies: ["keydown"],
    eventPriority: 0,
    phasedRegistrationNames: { bubbled: "onKeyDown", captured: "onKeyDownCapture" }
  },
  eventPhase: undefined,
  isDefaultPrevented: function functionThatReturnsFalse() {},
  isPersistent: function functionThatReturnsTrue() {},
  isPropagationStopped: function functionThatReturnsTrue() {},
  isTrusted: undefined,
  key: " ",
  nativeEvent: [Event] { cancelBubble: true, target: <div class="childElement"></div>, type: "keydown" },
  target: <div class="childElement"></div>,
  timeStamp: 1612787515578,
  type: "keydown"
}) at ActionResolver._handleMatchFound (D:\GitHub\react-hotkeys\src\lib\matching\/ActionResolver.js:194:17)

    handler([SyntheticEvent] {
  _dispatchInstances: null,
  _dispatchListeners: null,
  _targetInst: [FiberNode] {
    _debugHookTypes: null,
    _debugID: 138,
    _debugIsCurrentlyTiming: false,
    _debugNeedsRemount: false,
    _debugOwner: null,
    _debugSource: null,
    actualDuration: 0,
    actualStartTime: -1,
    alternate: null,
    child: null,
    childExpirationTime: 0,
    dependencies: null,
    effectTag: 0,
    elementType: "div",
    expirationTime: 0,
    firstEffect: null,
    index: 0,
    key: null,
    lastEffect: null,
    memoizedProps: { className: "childElement" },
    memoizedState: null,
    mode: 0,
    nextEffect: null,
    pendingProps: [Circular],
    ref: null,
    return: [FiberNode] {
      _debugHookTypes: null,
      _debugID: 136,
      _debugIsCurrentlyTiming: false,
      _debugNeedsRemount: false,
      _debugOwner: [FiberNode] {
        _debugHookTypes: null,
        _debugID: 134,
        _debugIsCurrentlyTiming: false,
        _debugNeedsRemount: false,
        _debugOwner: [FiberNode] {
          _debugHookTypes: null,
          _debugID: 130,
          _debugIsCurrentlyTiming: false,
          _debugNeedsRemount: false,
          _debugOwner: [FiberNode] {
            _debugHookTypes: null,
            _debugID: 128,
            _debugIsCurrentlyTiming: false,
            _debugNeedsRemount: false,
            _debugOwner: null,
            _debugSource: null,
            actualDuration: 0,
            actualStartTime: -1,
            alternate: null,
            child: [Circular],
            childExpirationTime: 0,
            dependencies: null,
            effectTag: 1,
            elementType: function WrapperComponent() {},
            expirationTime: 0,
            firstEffect: [Circular],
            index: 0,
            key: null,
            lastEffect: [Circular],
            memoizedProps: {
              Component: function HotKeysEnabled() {},
              context: null,
              props: {
                children: {
                  $$typeof: Symbol(react.element),
                  _owner: null,
                  _store: {  },
                  key: null,
                  props: [Circular],
                  ref: null,
                  type: "div"
                },
                handlers: { ACTION1: function spy() {}, ACTION2: function spy() {} },
                keyMap: { ACTION1: "shift+space", ACTION2: "shift+r" }
              },
              refProp: null,
              wrappingComponentProps: null
            },
            memoizedState: {
              context: null,
              mount: true,
              props: [Circular],
              wrappingComponentProps: null
            },
            mode: 0,
            nextEffect: null,
            pendingProps: [Circular],
            ref: null,
            return: [FiberNode] {
              _debugHookTypes: null,
              _debugID: 125,
              _debugIsCurrentlyTiming: false,
              _debugNeedsRemount: false,
              _debugOwner: null,
              _debugSource: null,
              actualDuration: 0,
              actualStartTime: -1,
              alternate: [FiberNode] {
                _debugHookTypes: null,
                _debugID: 125,
                _debugIsCurrentlyTiming: false,
                _debugNeedsRemount: false,
                _debugOwner: null,
                _debugSource: null,
                actualDuration: 0,
                actualStartTime: -1,
                alternate: [Circular],
                child: null,
                childExpirationTime: 0,
                dependencies: null,
                effectTag: 0,
                elementType: null,
                expirationTime: 1073741823,
                firstEffect: null,
                index: 0,
                key: null,
                lastEffect: null,
                memoizedProps: null,
                memoizedState: null,
                mode: 0,
                nextEffect: null,
                pendingProps: null,
                ref: null,
                return: null,
                selfBaseDuration: 0,
                sibling: null,
                stateNode: [FiberRootNode] {
                  callbackExpirationTime: 0,
                  callbackNode: null,
                  callbackPriority: 90,
                  containerInfo: <div><div tabindex="-1"><[...]</div>,
                  context: {  },
                  current: [Circular],
                  finishedExpirationTime: 0,
                  finishedWork: null,
                  firstPendingTime: 0,
                  firstSuspendedTime: 0,
                  hydrate: false,
                  interactionThreadID: 17,
                  lastExpiredTime: 0,
                  lastPingedTime: 0,
                  lastSuspendedTime: 0,
                  memoizedInteractions: Set {},
                  nextKnownPendingLevel: 0,
                  pendingChildren: null,
                  pendingContext: null,
                  pendingInteractionMap: [Map] {  },
                  pingCache: null,
                  tag: 0,
                  timeoutHandle: -1
                },
                tag: 3,
                treeBaseDuration: 0,
                type: null,
                updateQueue: {
                  baseQueue: {
                    callback: null,
                    expirationTime: 1073741823,
                    next: [Circular],
                    payload: {
                      element: {
                        $$typeof: Symbol(react.element),
                        _owner: null,
                        _store: {  },
                        key: null,
                        props: [Circular],
                        ref: null,
                        type: function WrapperComponent() {}
                      }
                    },
                    priority: 97,
                    suspenseConfig: null,
                    tag: 0
                  },
                  baseState: null,
                  effects: null,
                  shared: { pending: null }
                }
              },
              child: [Circular],
              childExpirationTime: 0,
              dependencies: null,
              effectTag: 0,
              elementType: null,
              expirationTime: 0,
              firstEffect: [Circular],
              index: 0,
              key: null,
              lastEffect: [Circular],
              memoizedProps: null,
              memoizedState: { element: [Circular] },
              mode: 0,
              nextEffect: null,
              pendingProps: null,
              ref: null,
              return: null,
              selfBaseDuration: 0,
              sibling: null,
              stateNode: [Circular],
              tag: 3,
              treeBaseDuration: 0,
              type: null,
              updateQueue: {
                baseQueue: null,
                baseState: [Circular],
                effects: null,
                shared: [Circular]
              }
            },
            selfBaseDuration: 0,
            sibling: null,
            stateNode: [WrapperComponent] {
              _reactInternalFiber: [Circular],
              _reactInternalInstance: {  },
              context: [Circular],
              props: [Circular],
              refs: {  },
              state: [Circular],
              updater: {
                enqueueForceUpdate: function enqueueForceUpdate() {},
                enqueueReplaceState: function enqueueReplaceState() {},
                enqueueSetState: function enqueueSetState() {},
                isMounted: function isMounted() {}
              }
            },
            tag: 1,
            treeBaseDuration: 0,
            type: function WrapperComponent() {},
            updateQueue: {
              baseQueue: null,
              baseState: [Circular],
              effects: null,
              shared: { pending: null }
            }
          },
          _debugSource: null,
          actualDuration: 0,
          actualStartTime: -1,
          alternate: null,
          child: [FiberNode] {
            _debugHookTypes: null,
            _debugID: 132,
            _debugIsCurrentlyTiming: false,
            _debugNeedsRemount: false,
            _debugOwner: [Circular],
            _debugSource: null,
            actualDuration: 0,
            actualStartTime: -1,
            alternate: null,
            child: [Circular],
            childExpirationTime: 0,
            dependencies: null,
            effectTag: 0,
            elementType: {
              $$typeof: Symbol(react.provider),
              _context: {
                $$typeof: Symbol(react.context),
                Consumer: {
                  $$typeof: Symbol(react.context),
                  _calculateChangedBits: null,
                  _context: [Circular]
                },
                Provider: [Circular],
                _calculateChangedBits: null,
                _currentRenderer: {  },
                _currentRenderer2: null,
                _currentValue: { hotKeysParentId: undefined },
                _currentValue2: [Circular],
                _threadCount: 0
              }
            },
            expirationTime: 0,
            firstEffect: null,
            index: 0,
            key: null,
            lastEffect: null,
            memoizedProps: {
              children: {
                $$typeof: Symbol(react.element),
                _owner: [Circular],
                _store: {  },
                key: null,
                props: {
                  children: [Circular],
                  hotKeys: {
                    onBlur: function () {},
                    onFocus: function () {},
                    onKeyDown: function () {},
                    onKeyPress: function () {},
                    onKeyUp: function () {},
                    tabIndex: "-1"
                  }
                },
                ref: null,
                type: function HotKeysWrapper() {}
              },
              value: { hotKeysParentId: 0 }
            },
            memoizedState: null,
            mode: 0,
            nextEffect: null,
            pendingProps: [Circular],
            ref: null,
            return: [Circular],
            selfBaseDuration: 0,
            sibling: null,
            stateNode: null,
            tag: 10,
            treeBaseDuration: 0,
            type: [Circular],
            updateQueue: null
          },
          childExpirationTime: 0,
          dependencies: {
            expirationTime: 0,
            firstContext: { context: [Circular], next: null, observedBits: 1073741823 },
            responders: null
          },
          effectTag: 5,
          elementType: function HotKeysEnabled() {},
          expirationTime: 0,
          firstEffect: null,
          index: 0,
          key: null,
          lastEffect: null,
          memoizedProps: { children: [Circular], handlers: [Circular], keyMap: [Circular] },
          memoizedState: null,
          mode: 0,
          nextEffect: null,
          pendingProps: [Circular],
          ref: null,
          return: [Circular],
          selfBaseDuration: 0,
          sibling: null,
          stateNode: [HotKeysEnabled] {
            _manager: [FocusOnlyComponentManager] {
              _focusTreeIds: [1],
              _focused: true,
              _hotKeysOptions: {  },
              childContext: [Circular],
              id: 0
            },
            _reactInternalFiber: [Circular],
            _reactInternalInstance: [Circular],
            context: [Circular],
            props: [Circular],
            refs: [Circular],
            state: null,
            updater: [Circular]
          },
          tag: 1,
          treeBaseDuration: 0,
          type: function HotKeysEnabled() {},
          updateQueue: {
            baseQueue: null,
            baseState: null,
            effects: null,
            shared: { pending: null }
          }
        },
        _debugSource: null,
        actualDuration: 0,
        actualStartTime: -1,
        alternate: null,
        child: [Circular],
        childExpirationTime: 0,
        dependencies: null,
        effectTag: 1,
        elementType: function HotKeysWrapper() {},
        expirationTime: 0,
        firstEffect: null,
        index: 0,
        key: null,
        lastEffect: null,
        memoizedProps: [Circular],
        memoizedState: null,
        mode: 0,
        nextEffect: null,
        pendingProps: [Circular],
        ref: null,
        return: [Circular],
        selfBaseDuration: 0,
        sibling: null,
        stateNode: [HotKeysWrapper] {
          _reactInternalFiber: [Circular],
          _reactInternalInstance: [Circular],
          context: [Circular],
          props: [Circular],
          refs: [Circular],
          state: null,
          updater: [Circular]
        },
        tag: 1,
        treeBaseDuration: 0,
        type: function HotKeysWrapper() {},
        updateQueue: { baseQueue: null, baseState: null, effects: null, shared: { pending: null } }
      },
      _debugSource: null,
      actualDuration: 0,
      actualStartTime: -1,
      alternate: null,
      child: [Circular],
      childExpirationTime: 0,
      dependencies: null,
      effectTag: 0,
      elementType: "div",
      expirationTime: 0,
      firstEffect: null,
      index: 0,
      key: null,
      lastEffect: null,
      memoizedProps: {
        children: [Circular],
        onBlur: function () {},
        onFocus: function () {},
        onKeyDown: function () {},
        onKeyPress: function () {},
        onKeyUp: function () {},
        tabIndex: "-1"
      },
      memoizedState: null,
      mode: 0,
      nextEffect: null,
      pendingProps: [Circular],
      ref: null,
      return: [Circular],
      selfBaseDuration: 0,
      sibling: null,
      stateNode: <div tabindex="-1"><div class="childEle[...]</div>,
      tag: 5,
      treeBaseDuration: 0,
      type: "div",
      updateQueue: null
    },
    selfBaseDuration: 0,
    sibling: null,
    stateNode: <div class="childElement"></div>,
    tag: 5,
    treeBaseDuration: 0,
    type: "div",
    updateQueue: null
  },
  bubbles: undefined,
  cancelable: undefined,
  currentTarget: null,
  defaultPrevented: undefined,
  dispatchConfig: {
    dependencies: ["keydown"],
    eventPriority: 0,
    phasedRegistrationNames: { bubbled: "onKeyDown", captured: "onKeyDownCapture" }
  },
  eventPhase: undefined,
  isDefaultPrevented: function functionThatReturnsFalse() {},
  isPersistent: function functionThatReturnsTrue() {},
  isPropagationStopped: function functionThatReturnsTrue() {},
  isTrusted: undefined,
  key: "Shift",
  nativeEvent: [Event] { cancelBubble: true, target: <div class="childElement"></div>, type: "keydown" },
  target: <div class="childElement"></div>,
  timeStamp: 1612787515581,
  type: "keydown"
}) at ActionResolver._handleMatchFound (D:\GitHub\react-hotkeys\src\lib\matching\/ActionResolver.js:194:17)
AssertionError: expected handler to have been called exactly once, but it was called twice
    handler([SyntheticEvent] {
  _dispatchInstances: null,
  _dispatchListeners: null,
  _targetInst: [FiberNode] {
    _debugHookTypes: null,
    _debugID: 138,
    _debugIsCurrentlyTiming: false,
    _debugNeedsRemount: false,
    _debugOwner: null,
    _debugSource: null,
    actualDuration: 0,
    actualStartTime: -1,
    alternate: null,
    child: null,
    childExpirationTime: 0,
    dependencies: null,
    effectTag: 0,
    elementType: "div",
    expirationTime: 0,
    firstEffect: null,
    index: 0,
    key: null,
    lastEffect: null,
    memoizedProps: { className: "childElement" },
    memoizedState: null,
    mode: 0,
    nextEffect: null,
    pendingProps: [Circular],
    ref: null,
    return: [FiberNode] {
      _debugHookTypes: null,
      _debugID: 136,
      _debugIsCurrentlyTiming: false,
      _debugNeedsRemount: false,
      _debugOwner: [FiberNode] {
        _debugHookTypes: null,
        _debugID: 134,
        _debugIsCurrentlyTiming: false,
        _debugNeedsRemount: false,
        _debugOwner: [FiberNode] {
          _debugHookTypes: null,
          _debugID: 130,
          _debugIsCurrentlyTiming: false,
          _debugNeedsRemount: false,
          _debugOwner: [FiberNode] {
            _debugHookTypes: null,
            _debugID: 128,
            _debugIsCurrentlyTiming: false,
            _debugNeedsRemount: false,
            _debugOwner: null,
            _debugSource: null,
            actualDuration: 0,
            actualStartTime: -1,
            alternate: null,
            child: [Circular],
            childExpirationTime: 0,
            dependencies: null,
            effectTag: 1,
            elementType: function WrapperComponent() {},
            expirationTime: 0,
            firstEffect: [Circular],
            index: 0,
            key: null,
            lastEffect: [Circular],
            memoizedProps: {
              Component: function HotKeysEnabled() {},
              context: null,
              props: {
                children: {
                  $$typeof: Symbol(react.element),
                  _owner: null,
                  _store: {  },
                  key: null,
                  props: [Circular],
                  ref: null,
                  type: "div"
                },
                handlers: { ACTION1: function spy() {}, ACTION2: function spy() {} },
                keyMap: { ACTION1: "shift+space", ACTION2: "shift+r" }
              },
              refProp: null,
              wrappingComponentProps: null
            },
            memoizedState: {
              context: null,
              mount: true,
              props: [Circular],
              wrappingComponentProps: null
            },
            mode: 0,
            nextEffect: null,
            pendingProps: [Circular],
            ref: null,
            return: [FiberNode] {
              _debugHookTypes: null,
              _debugID: 125,
              _debugIsCurrentlyTiming: false,
              _debugNeedsRemount: false,
              _debugOwner: null,
              _debugSource: null,
              actualDuration: 0,
              actualStartTime: -1,
              alternate: [FiberNode] {
                _debugHookTypes: null,
                _debugID: 125,
                _debugIsCurrentlyTiming: false,
                _debugNeedsRemount: false,
                _debugOwner: null,
                _debugSource: null,
                actualDuration: 0,
                actualStartTime: -1,
                alternate: [Circular],
                child: null,
                childExpirationTime: 0,
                dependencies: null,
                effectTag: 0,
                elementType: null,
                expirationTime: 1073741823,
                firstEffect: null,
                index: 0,
                key: null,
                lastEffect: null,
                memoizedProps: null,
                memoizedState: null,
                mode: 0,
                nextEffect: null,
                pendingProps: null,
                ref: null,
                return: null,
                selfBaseDuration: 0,
                sibling: null,
                stateNode: [FiberRootNode] {
                  callbackExpirationTime: 0,
                  callbackNode: null,
                  callbackPriority: 90,
                  containerInfo: <div><div tabindex="-1"><[...]</div>,
                  context: {  },
                  current: [Circular],
                  finishedExpirationTime: 0,
                  finishedWork: null,
                  firstPendingTime: 0,
                  firstSuspendedTime: 0,
                  hydrate: false,
                  interactionThreadID: 17,
                  lastExpiredTime: 0,
                  lastPingedTime: 0,
                  lastSuspendedTime: 0,
                  memoizedInteractions: Set {},
                  nextKnownPendingLevel: 0,
                  pendingChildren: null,
                  pendingContext: null,
                  pendingInteractionMap: [Map] {  },
                  pingCache: null,
                  tag: 0,
                  timeoutHandle: -1
                },
                tag: 3,
                treeBaseDuration: 0,
                type: null,
                updateQueue: {
                  baseQueue: {
                    callback: null,
                    expirationTime: 1073741823,
                    next: [Circular],
                    payload: {
                      element: {
                        $$typeof: Symbol(react.element),
                        _owner: null,
                        _store: {  },
                        key: null,
                        props: [Circular],
                        ref: null,
                        type: function WrapperComponent() {}
                      }
                    },
                    priority: 97,
                    suspenseConfig: null,
                    tag: 0
                  },
                  baseState: null,
                  effects: null,
                  shared: { pending: null }
                }
              },
              child: [Circular],
              childExpirationTime: 0,
              dependencies: null,
              effectTag: 0,
              elementType: null,
              expirationTime: 0,
              firstEffect: [Circular],
              index: 0,
              key: null,
              lastEffect: [Circular],
              memoizedProps: null,
              memoizedState: { element: [Circular] },
              mode: 0,
              nextEffect: null,
              pendingProps: null,
              ref: null,
              return: null,
              selfBaseDuration: 0,
              sibling: null,
              stateNode: [Circular],
              tag: 3,
              treeBaseDuration: 0,
              type: null,
              updateQueue: {
                baseQueue: null,
                baseState: [Circular],
                effects: null,
                shared: [Circular]
              }
            },
            selfBaseDuration: 0,
            sibling: null,
            stateNode: [WrapperComponent] {
              _reactInternalFiber: [Circular],
              _reactInternalInstance: {  },
              context: [Circular],
              props: [Circular],
              refs: {  },
              state: [Circular],
              updater: {
                enqueueForceUpdate: function enqueueForceUpdate() {},
                enqueueReplaceState: function enqueueReplaceState() {},
                enqueueSetState: function enqueueSetState() {},
                isMounted: function isMounted() {}
              }
            },
            tag: 1,
            treeBaseDuration: 0,
            type: function WrapperComponent() {},
            updateQueue: {
              baseQueue: null,
              baseState: [Circular],
              effects: null,
              shared: { pending: null }
            }
          },
          _debugSource: null,
          actualDuration: 0,
          actualStartTime: -1,
          alternate: null,
          child: [FiberNode] {
            _debugHookTypes: null,
            _debugID: 132,
            _debugIsCurrentlyTiming: false,
            _debugNeedsRemount: false,
            _debugOwner: [Circular],
            _debugSource: null,
            actualDuration: 0,
            actualStartTime: -1,
            alternate: null,
            child: [Circular],
            childExpirationTime: 0,
            dependencies: null,
            effectTag: 0,
            elementType: {
              $$typeof: Symbol(react.provider),
              _context: {
                $$typeof: Symbol(react.context),
                Consumer: {
                  $$typeof: Symbol(react.context),
                  _calculateChangedBits: null,
                  _context: [Circular]
                },
                Provider: [Circular],
                _calculateChangedBits: null,
                _currentRenderer: {  },
                _currentRenderer2: null,
                _currentValue: { hotKeysParentId: undefined },
                _currentValue2: [Circular],
                _threadCount: 0
              }
            },
            expirationTime: 0,
            firstEffect: null,
            index: 0,
            key: null,
            lastEffect: null,
            memoizedProps: {
              children: {
                $$typeof: Symbol(react.element),
                _owner: [Circular],
                _store: {  },
                key: null,
                props: {
                  children: [Circular],
                  hotKeys: {
                    onBlur: function () {},
                    onFocus: function () {},
                    onKeyDown: function () {},
                    onKeyPress: function () {},
                    onKeyUp: function () {},
                    tabIndex: "-1"
                  }
                },
                ref: null,
                type: function HotKeysWrapper() {}
              },
              value: { hotKeysParentId: 0 }
            },
            memoizedState: null,
            mode: 0,
            nextEffect: null,
            pendingProps: [Circular],
            ref: null,
            return: [Circular],
            selfBaseDuration: 0,
            sibling: null,
            stateNode: null,
            tag: 10,
            treeBaseDuration: 0,
            type: [Circular],
            updateQueue: null
          },
          childExpirationTime: 0,
          dependencies: {
            expirationTime: 0,
            firstContext: { context: [Circular], next: null, observedBits: 1073741823 },
            responders: null
          },
          effectTag: 5,
          elementType: function HotKeysEnabled() {},
          expirationTime: 0,
          firstEffect: null,
          index: 0,
          key: null,
          lastEffect: null,
          memoizedProps: { children: [Circular], handlers: [Circular], keyMap: [Circular] },
          memoizedState: null,
          mode: 0,
          nextEffect: null,
          pendingProps: [Circular],
          ref: null,
          return: [Circular],
          selfBaseDuration: 0,
          sibling: null,
          stateNode: [HotKeysEnabled] {
            _manager: [FocusOnlyComponentManager] {
              _focusTreeIds: [1],
              _focused: true,
              _hotKeysOptions: {  },
              childContext: [Circular],
              id: 0
            },
            _reactInternalFiber: [Circular],
            _reactInternalInstance: [Circular],
            context: [Circular],
            props: [Circular],
            refs: [Circular],
            state: null,
            updater: [Circular]
          },
          tag: 1,
          treeBaseDuration: 0,
          type: function HotKeysEnabled() {},
          updateQueue: {
            baseQueue: null,
            baseState: null,
            effects: null,
            shared: { pending: null }
          }
        },
        _debugSource: null,
        actualDuration: 0,
        actualStartTime: -1,
        alternate: null,
        child: [Circular],
        childExpirationTime: 0,
        dependencies: null,
        effectTag: 1,
        elementType: function HotKeysWrapper() {},
        expirationTime: 0,
        firstEffect: null,
        index: 0,
        key: null,
        lastEffect: null,
        memoizedProps: [Circular],
        memoizedState: null,
        mode: 0,
        nextEffect: null,
        pendingProps: [Circular],
        ref: null,
        return: [Circular],
        selfBaseDuration: 0,
        sibling: null,
        stateNode: [HotKeysWrapper] {
          _reactInternalFiber: [Circular],
          _reactInternalInstance: [Circular],
          context: [Circular],
          props: [Circular],
          refs: [Circular],
          state: null,
          updater: [Circular]
        },
        tag: 1,
        treeBaseDuration: 0,
        type: function HotKeysWrapper() {},
        updateQueue: { baseQueue: null, baseState: null, effects: null, shared: { pending: null } }
      },
      _debugSource: null,
      actualDuration: 0,
      actualStartTime: -1,
      alternate: null,
      child: [Circular],
      childExpirationTime: 0,
      dependencies: null,
      effectTag: 0,
      elementType: "div",
      expirationTime: 0,
      firstEffect: null,
      index: 0,
      key: null,
      lastEffect: null,
      memoizedProps: {
        children: [Circular],
        onBlur: function () {},
        onFocus: function () {},
        onKeyDown: function () {},
        onKeyPress: function () {},
        onKeyUp: function () {},
        tabIndex: "-1"
      },
      memoizedState: null,
      mode: 0,
      nextEffect: null,
      pendingProps: [Circular],
      ref: null,
      return: [Circular],
      selfBaseDuration: 0,
      sibling: null,
      stateNode: <div tabindex="-1"><div class="childEle[...]</div>,
      tag: 5,
      treeBaseDuration: 0,
      type: "div",
      updateQueue: null
    },
    selfBaseDuration: 0,
    sibling: null,
    stateNode: <div class="childElement"></div>,
    tag: 5,
    treeBaseDuration: 0,
    type: "div",
    updateQueue: null
  },
  bubbles: undefined,
  cancelable: undefined,
  currentTarget: null,
  defaultPrevented: undefined,
  dispatchConfig: {
    dependencies: ["keydown"],
    eventPriority: 0,
    phasedRegistrationNames: { bubbled: "onKeyDown", captured: "onKeyDownCapture" }
  },
  eventPhase: undefined,
  isDefaultPrevented: function functionThatReturnsFalse() {},
  isPersistent: function functionThatReturnsTrue() {},
  isPropagationStopped: function functionThatReturnsTrue() {},
  isTrusted: undefined,
  key: " ",
  nativeEvent: [Event] { cancelBubble: true, target: <div class="childElement"></div>, type: "keydown" },
  target: <div class="childElement"></div>,
  timeStamp: 1612787515578,
  type: "keydown"
}) at ActionResolver._handleMatchFound (src\lib\matching\/ActionResolver.js:194:17)

    handler([SyntheticEvent] {
  _dispatchInstances: null,
  _dispatchListeners: null,
  _targetInst: [FiberNode] {
    _debugHookTypes: null,
    _debugID: 138,
    _debugIsCurrentlyTiming: false,
    _debugNeedsRemount: false,
    _debugOwner: null,
    _debugSource: null,
    actualDuration: 0,
    actualStartTime: -1,
    alternate: null,
    child: null,
    childExpirationTime: 0,
    dependencies: null,
    effectTag: 0,
    elementType: "div",
    expirationTime: 0,
    firstEffect: null,
    index: 0,
    key: null,
    lastEffect: null,
    memoizedProps: { className: "childElement" },
    memoizedState: null,
    mode: 0,
    nextEffect: null,
    pendingProps: [Circular],
    ref: null,
    return: [FiberNode] {
      _debugHookTypes: null,
      _debugID: 136,
      _debugIsCurrentlyTiming: false,
      _debugNeedsRemount: false,
      _debugOwner: [FiberNode] {
        _debugHookTypes: null,
        _debugID: 134,
        _debugIsCurrentlyTiming: false,
        _debugNeedsRemount: false,
        _debugOwner: [FiberNode] {
          _debugHookTypes: null,
          _debugID: 130,
          _debugIsCurrentlyTiming: false,
          _debugNeedsRemount: false,
          _debugOwner: [FiberNode] {
            _debugHookTypes: null,
            _debugID: 128,
            _debugIsCurrentlyTiming: false,
            _debugNeedsRemount: false,
            _debugOwner: null,
            _debugSource: null,
            actualDuration: 0,
            actualStartTime: -1,
            alternate: null,
            child: [Circular],
            childExpirationTime: 0,
            dependencies: null,
            effectTag: 1,
            elementType: function WrapperComponent() {},
            expirationTime: 0,
            firstEffect: [Circular],
            index: 0,
            key: null,
            lastEffect: [Circular],
            memoizedProps: {
              Component: function HotKeysEnabled() {},
              context: null,
              props: {
                children: {
                  $$typeof: Symbol(react.element),
                  _owner: null,
                  _store: {  },
                  key: null,
                  props: [Circular],
                  ref: null,
                  type: "div"
                },
                handlers: { ACTION1: function spy() {}, ACTION2: function spy() {} },
                keyMap: { ACTION1: "shift+space", ACTION2: "shift+r" }
              },
              refProp: null,
              wrappingComponentProps: null
            },
            memoizedState: {
              context: null,
              mount: true,
              props: [Circular],
              wrappingComponentProps: null
            },
            mode: 0,
            nextEffect: null,
            pendingProps: [Circular],
            ref: null,
            return: [FiberNode] {
              _debugHookTypes: null,
              _debugID: 125,
              _debugIsCurrentlyTiming: false,
              _debugNeedsRemount: false,
              _debugOwner: null,
              _debugSource: null,
              actualDuration: 0,
              actualStartTime: -1,
              alternate: [FiberNode] {
                _debugHookTypes: null,
                _debugID: 125,
                _debugIsCurrentlyTiming: false,
                _debugNeedsRemount: false,
                _debugOwner: null,
                _debugSource: null,
                actualDuration: 0,
                actualStartTime: -1,
                alternate: [Circular],
                child: null,
                childExpirationTime: 0,
                dependencies: null,
                effectTag: 0,
                elementType: null,
                expirationTime: 1073741823,
                firstEffect: null,
                index: 0,
                key: null,
                lastEffect: null,
                memoizedProps: null,
                memoizedState: null,
                mode: 0,
                nextEffect: null,
                pendingProps: null,
                ref: null,
                return: null,
                selfBaseDuration: 0,
                sibling: null,
                stateNode: [FiberRootNode] {
                  callbackExpirationTime: 0,
                  callbackNode: null,
                  callbackPriority: 90,
                  containerInfo: <div><div tabindex="-1"><[...]</div>,
                  context: {  },
                  current: [Circular],
                  finishedExpirationTime: 0,
                  finishedWork: null,
                  firstPendingTime: 0,
                  firstSuspendedTime: 0,
                  hydrate: false,
                  interactionThreadID: 17,
                  lastExpiredTime: 0,
                  lastPingedTime: 0,
                  lastSuspendedTime: 0,
                  memoizedInteractions: Set {},
                  nextKnownPendingLevel: 0,
                  pendingChildren: null,
                  pendingContext: null,
                  pendingInteractionMap: [Map] {  },
                  pingCache: null,
                  tag: 0,
                  timeoutHandle: -1
                },
                tag: 3,
                treeBaseDuration: 0,
                type: null,
                updateQueue: {
                  baseQueue: {
                    callback: null,
                    expirationTime: 1073741823,
                    next: [Circular],
                    payload: {
                      element: {
                        $$typeof: Symbol(react.element),
                        _owner: null,
                        _store: {  },
                        key: null,
                        props: [Circular],
                        ref: null,
                        type: function WrapperComponent() {}
                      }
                    },
                    priority: 97,
                    suspenseConfig: null,
                    tag: 0
                  },
                  baseState: null,
                  effects: null,
                  shared: { pending: null }
                }
              },
              child: [Circular],
              childExpirationTime: 0,
              dependencies: null,
              effectTag: 0,
              elementType: null,
              expirationTime: 0,
              firstEffect: [Circular],
              index: 0,
              key: null,
              lastEffect: [Circular],
              memoizedProps: null,
              memoizedState: { element: [Circular] },
              mode: 0,
              nextEffect: null,
              pendingProps: null,
              ref: null,
              return: null,
              selfBaseDuration: 0,
              sibling: null,
              stateNode: [Circular],
              tag: 3,
              treeBaseDuration: 0,
              type: null,
              updateQueue: {
                baseQueue: null,
                baseState: [Circular],
                effects: null,
                shared: [Circular]
              }
            },
            selfBaseDuration: 0,
            sibling: null,
            stateNode: [WrapperComponent] {
              _reactInternalFiber: [Circular],
              _reactInternalInstance: {  },
              context: [Circular],
              props: [Circular],
              refs: {  },
              state: [Circular],
              updater: {
                enqueueForceUpdate: function enqueueForceUpdate() {},
                enqueueReplaceState: function enqueueReplaceState() {},
                enqueueSetState: function enqueueSetState() {},
                isMounted: function isMounted() {}
              }
            },
            tag: 1,
            treeBaseDuration: 0,
            type: function WrapperComponent() {},
            updateQueue: {
              baseQueue: null,
              baseState: [Circular],
              effects: null,
              shared: { pending: null }
            }
          },
          _debugSource: null,
          actualDuration: 0,
          actualStartTime: -1,
          alternate: null,
          child: [FiberNode] {
            _debugHookTypes: null,
            _debugID: 132,
            _debugIsCurrentlyTiming: false,
            _debugNeedsRemount: false,
            _debugOwner: [Circular],
            _debugSource: null,
            actualDuration: 0,
            actualStartTime: -1,
            alternate: null,
            child: [Circular],
            childExpirationTime: 0,
            dependencies: null,
            effectTag: 0,
            elementType: {
              $$typeof: Symbol(react.provider),
              _context: {
                $$typeof: Symbol(react.context),
                Consumer: {
                  $$typeof: Symbol(react.context),
                  _calculateChangedBits: null,
                  _context: [Circular]
                },
                Provider: [Circular],
                _calculateChangedBits: null,
                _currentRenderer: {  },
                _currentRenderer2: null,
                _currentValue: { hotKeysParentId: undefined },
                _currentValue2: [Circular],
                _threadCount: 0
              }
            },
            expirationTime: 0,
            firstEffect: null,
            index: 0,
            key: null,
            lastEffect: null,
            memoizedProps: {
              children: {
                $$typeof: Symbol(react.element),
                _owner: [Circular],
                _store: {  },
                key: null,
                props: {
                  children: [Circular],
                  hotKeys: {
                    onBlur: function () {},
                    onFocus: function () {},
                    onKeyDown: function () {},
                    onKeyPress: function () {},
                    onKeyUp: function () {},
                    tabIndex: "-1"
                  }
                },
                ref: null,
                type: function HotKeysWrapper() {}
              },
              value: { hotKeysParentId: 0 }
            },
            memoizedState: null,
            mode: 0,
            nextEffect: null,
            pendingProps: [Circular],
            ref: null,
            return: [Circular],
            selfBaseDuration: 0,
            sibling: null,
            stateNode: null,
            tag: 10,
            treeBaseDuration: 0,
            type: [Circular],
            updateQueue: null
          },
          childExpirationTime: 0,
          dependencies: {
            expirationTime: 0,
            firstContext: { context: [Circular], next: null, observedBits: 1073741823 },
            responders: null
          },
          effectTag: 5,
          elementType: function HotKeysEnabled() {},
          expirationTime: 0,
          firstEffect: null,
          index: 0,
          key: null,
          lastEffect: null,
          memoizedProps: { children: [Circular], handlers: [Circular], keyMap: [Circular] },
          memoizedState: null,
          mode: 0,
          nextEffect: null,
          pendingProps: [Circular],
          ref: null,
          return: [Circular],
          selfBaseDuration: 0,
          sibling: null,
          stateNode: [HotKeysEnabled] {
            _manager: [FocusOnlyComponentManager] {
              _focusTreeIds: [1],
              _focused: true,
              _hotKeysOptions: {  },
              childContext: [Circular],
              id: 0
            },
            _reactInternalFiber: [Circular],
            _reactInternalInstance: [Circular],
            context: [Circular],
            props: [Circular],
            refs: [Circular],
            state: null,
            updater: [Circular]
          },
          tag: 1,
          treeBaseDuration: 0,
          type: function HotKeysEnabled() {},
          updateQueue: {
            baseQueue: null,
            baseState: null,
            effects: null,
            shared: { pending: null }
          }
        },
        _debugSource: null,
        actualDuration: 0,
        actualStartTime: -1,
        alternate: null,
        child: [Circular],
        childExpirationTime: 0,
        dependencies: null,
        effectTag: 1,
        elementType: function HotKeysWrapper() {},
        expirationTime: 0,
        firstEffect: null,
        index: 0,
        key: null,
        lastEffect: null,
        memoizedProps: [Circular],
        memoizedState: null,
        mode: 0,
        nextEffect: null,
        pendingProps: [Circular],
        ref: null,
        return: [Circular],
        selfBaseDuration: 0,
        sibling: null,
        stateNode: [HotKeysWrapper] {
          _reactInternalFiber: [Circular],
          _reactInternalInstance: [Circular],
          context: [Circular],
          props: [Circular],
          refs: [Circular],
          state: null,
          updater: [Circular]
        },
        tag: 1,
        treeBaseDuration: 0,
        type: function HotKeysWrapper() {},
        updateQueue: { baseQueue: null, baseState: null, effects: null, shared: { pending: null } }
      },
      _debugSource: null,
      actualDuration: 0,
      actualStartTime: -1,
      alternate: null,
      child: [Circular],
      childExpirationTime: 0,
      dependencies: null,
      effectTag: 0,
      elementType: "div",
      expirationTime: 0,
      firstEffect: null,
      index: 0,
      key: null,
      lastEffect: null,
      memoizedProps: {
        children: [Circular],
        onBlur: function () {},
        onFocus: function () {},
        onKeyDown: function () {},
        onKeyPress: function () {},
        onKeyUp: function () {},
        tabIndex: "-1"
      },
      memoizedState: null,
      mode: 0,
      nextEffect: null,
      pendingProps: [Circular],
      ref: null,
      return: [Circular],
      selfBaseDuration: 0,
      sibling: null,
      stateNode: <div tabindex="-1"><div class="childEle[...]</div>,
      tag: 5,
      treeBaseDuration: 0,
      type: "div",
      updateQueue: null
    },
    selfBaseDuration: 0,
    sibling: null,
    stateNode: <div class="childElement"></div>,
    tag: 5,
    treeBaseDuration: 0,
    type: "div",
    updateQueue: null
  },
  bubbles: undefined,
  cancelable: undefined,
  currentTarget: null,
  defaultPrevented: undefined,
  dispatchConfig: {
    dependencies: ["keydown"],
    eventPriority: 0,
    phasedRegistrationNames: { bubbled: "onKeyDown", captured: "onKeyDownCapture" }
  },
  eventPhase: undefined,
  isDefaultPrevented: function functionThatReturnsFalse() {},
  isPersistent: function functionThatReturnsTrue() {},
  isPropagationStopped: function functionThatReturnsTrue() {},
  isTrusted: undefined,
  key: "Shift",
  nativeEvent: [Event] { cancelBubble: true, target: <div class="childElement"></div>, type: "keydown" },
  target: <div class="childElement"></div>,
  timeStamp: 1612787515581,
  type: "keydown"
}) at ActionResolver._handleMatchFound (src\lib\matching\/ActionResolver.js:194:17)
    at Context.<anonymous> (test\HotKeys\/CombinationsInvolvingShiftKey.spec.js:92:7)

What Configuration options are you using?

configure({
  logLevel: "verbose"
})

Here is a small unit test demonstrating the issue (CombinationsInvolvingShiftKey.spec.js):

describe('and there are handlers defined for "shift+space" and "shift+r"', () => {
    beforeEach(function () {
      this.keyMap = {
        'ACTION1': 'shift+space',
        'ACTION2': 'shift+r'
      };

      this.handler1 = sinon.spy();
      this.handler2 = sinon.spy();

      const handlers = {
        'ACTION1': this.handler1,
        'ACTION2': this.handler2
      };

      this.wrapper = mount(
        <HotKeys keyMap={this.keyMap} handlers={handlers}>
          <div className="childElement" />
        </HotKeys>
      );

      this.targetElement = new FocusableElement(this.wrapper, '.childElement');
      this.targetElement.focus();
    });

    it(`then calls the handler for "Shift+space" and press "Shift"`, function() {
      this.targetElement.keyDown('Shift');
      this.targetElement.keyDown(' ');

      this.targetElement.focus();
      this.targetElement.keyDown('Shift');
      this.targetElement.keyUp('Shift');
      expect(this.handler1).to.have.been.calledOnce;
    });

    it(`then calls the handler for "Shift+space" and "Shift+r"`, function() {
      this.targetElement.keyDown('Shift');
      this.targetElement.keyDown(' ');

      this.targetElement.focus();
      this.targetElement.keyDown('Shift');
      this.targetElement.keyDown('r');
      this.targetElement.keyUp('r');
      this.targetElement.keyUp('Shift');
      expect(this.handler2).to.have.been.called;

    });

  });
@andrew-sv
Copy link
Author

andrew-sv commented Feb 8, 2021

I found out what is causing the issue. It seems Space and Enter key handlers simulate keyPress event even if these two keys can trigger native events. Here is the small program demonstrating which key triggers keyPress event in React. Sandbox
Space and Enter keys produce KeyPress event.
My suggestion is to fix it either in hasKeyPressEvent function (hasKeyPressEvent.js) or remove Space and Enter keys from translateToKey map (translateToKey.js). I prefer the second case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant