Skip to content

Instantly share code, notes, and snippets.

@corysimmons
Created May 23, 2020 15:37
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 corysimmons/a1883159c3608dcb5ef2c48c1e5e43fa to your computer and use it in GitHub Desktop.
Save corysimmons/a1883159c3608dcb5ef2c48c1e5e43fa to your computer and use it in GitHub Desktop.
import { useState, useLayoutEffect } from 'react'
const specialKeys = [
`Shift`,
`CapsLock`,
`Meta`,
`Control`,
`Alt`,
`Tab`,
`Backspace`,
`Escape`,
]
interface IHandlerProps {
key: string
shiftKey: boolean
repeat?: boolean
}
const useKeys = () => {
if (typeof window === `undefined`) return [] // Bail on SSR
const [keys, setKeys] = useState<IHandlerProps[]>([])
useLayoutEffect(() => {
const downHandler = ({ key, shiftKey, repeat }: IHandlerProps) => {
if (repeat) return // Bail if they're holding down a key
setKeys(prevKeys => {
return [
...prevKeys,
{
key,
shiftKey,
},
]
})
}
const upHandler = ({ key, shiftKey }: IHandlerProps) => {
setKeys(prevKeys => {
return prevKeys.filter(k => {
if (specialKeys.includes(key)) return false // Special keys being held down/let go of in certain orders would cause keys to get stuck in state
return JSON.stringify(k) !== JSON.stringify({ key, shiftKey })
})
})
}
window.addEventListener(`keydown`, downHandler)
window.addEventListener(`keyup`, upHandler)
return () => {
window.removeEventListener(`keydown`, downHandler)
window.removeEventListener(`keyup`, upHandler)
}
}, [])
return keys.map(x => x.key)
}
export default useKeys
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment