Skip to content

Instantly share code, notes, and snippets.

@jeremytenjo
Created December 30, 2020 02:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jeremytenjo/60dfb1ae98668861b08dce621ca1cff4 to your computer and use it in GitHub Desktop.
Save jeremytenjo/60dfb1ae98668861b08dce621ca1cff4 to your computer and use it in GitHub Desktop.
useKeyPress React hook with multiple key support
export default function useKeyPress(keys, onPress) {
keys = keys.split(' ').map((key) => key.toLowerCase())
const isSingleKey = keys.length === 1
const pressedKeys = useRef([])
const keyIsRequested = (key) => {
key = key.toLowerCase()
return keys.includes(key)
}
const addPressedKey = (key) => {
key = key.toLowerCase()
const update = pressedKeys.current.slice()
update.push(key)
pressedKeys.current = update
}
const removePressedKey = (key) => {
key = key.toLowerCase()
let update = pressedKeys.current.slice()
const index = update.findIndex((sKey) => sKey === key)
update = update.slice(0, index)
pressedKeys.current = update
}
const downHandler = ({ key }) => {
const isKeyRequested = keyIsRequested(key)
if (isKeyRequested) {
addPressedKey(key)
}
}
const upHandler = ({ key }) => {
const isKeyRequested = keyIsRequested(key)
if (isKeyRequested) {
if (isSingleKey) {
pressedKeys.current = []
onPress()
} else {
const containsAll = keys.every((i) => pressedKeys.current.includes(i))
removePressedKey(key)
if (containsAll) {
onPress()
}
}
}
}
useEffect(() => {
window.addEventListener('keydown', downHandler)
window.addEventListener('keyup', upHandler)
return () => {
window.removeEventListener('keydown', downHandler)
window.removeEventListener('keyup', upHandler)
}
}, [])
}
@jeremytenjo
Copy link
Author

jeremytenjo commented Dec 30, 2020

Usage (Codesandbox):

function testUseKeyPress() {
 const onPressSingle = () => {
    console.log('onPressSingle!')
  }
  const onPressMulti = () => {
    console.log('onPressMulti!')
  }

  useKeyPress('a', onPressSingle)
  useKeyPress('shift h', onPressMulti)
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment