use-key
v1.0.1
Published
React hook for registering keybinds
Downloads
3
Readme
useKey
useKey is a react hook for registering keybinds.
Installation
$ yarn add use-key
Usage
Function signature:
interface Keybinds {
[keybind: string]: Callback
}
useKey(keybinds: Keybinds)
Examples:
// Single keys
useKey({
'Escape': () => console.log('action')
})
// Modifier combinations
useKey({
'Meta+Shift+z': () => console.log('action')
})
// Key sequences (callback fires when you press "w", then "s", then "d")
useKey({
'w s d': () => console.log('action')
})
// Space key in sequence (`w ' ' d` also works)
useKey(
'w " " d': () => console.log('action')
})
// Multiple key combinations mapped to the same callback
useKey({
'Control+z, Meta+z': () => console.log('action')
})
useKey({
'a, Meta+z, w s d': () => console.log('action')
})
// Multiple keybinds registered at once
useKey({
'a': () => console.log('action'),
'b': () => console.log('action 2')
})
Errors
useKey throws an error if you register the same keybind twice.
useKey('a', () => console.log('action'))
useKey('a', () => console.log('action 2'))
// => Error: Keybind "a" already in use.
This also applies to keybinds using modifier combinations and sequences.
Specifics
For every useKey
, there is an associated useEffect
. Across every useKey
, there is only one shared event listener that handles every keybind.
Why? This means you can register a lot of keybinds without adding many global listeners. This should (theoretically) improve performance with a large number of registered keybinds. I also just wanted to see if and how it would work.
Future Work
Notes to self, things to add.
Scoping
Allow keybinds to be scoped to a DOM element instead of being global. Listeners should be deduped, just like global ones.
Support both string
and React.Ref
for selector?
useKey({
'a': {
ref: 'div.container',
callback: () => console.log('action')
}
})
Configurable delays
Allow the delay for key sequences to be configurable. If after maxDelay
milliseconds the next key in the sequence hasn't been pressed, reset the list of already pressed keys.
useKey({
'a b c': {
callback: () => console.log('action'),
maxDelay: 500
}
})
Export KeyHandler
Useful class, may as well expose it.
import { KeyHandler } from 'use-key'
const handler = new KeyHandler('a', () => console.log('action'))
window.addEventListener('keydown', handler.handle)
Bugs
- Triggering a callback doesn't clear the all of the sequence timers
Credits
useKey
is inspired by and based on the logic in react-use-hotkeys
.
Thanks to Giuseppe for ideas on how to share event listeners across multiple calls to a hook.