use-key
TypeScript icon, indicating that this package has built-in type declarations

1.0.1 • Public • Published

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.

Readme

Keywords

none

Package Sidebar

Install

npm i use-key

Weekly Downloads

2

Version

1.0.1

License

MIT

Unpacked Size

48.4 kB

Total Files

15

Last publish

Collaborators

  • paco