Skip to content

Instantly share code, notes, and snippets.

@RodrigoNovais
Last active May 15, 2021 14:42
Show Gist options
  • Save RodrigoNovais/8bc2ea47f1dd4c665b4fb8d94b98e669 to your computer and use it in GitHub Desktop.
Save RodrigoNovais/8bc2ea47f1dd4c665b4fb8d94b98e669 to your computer and use it in GitHub Desktop.
Custom react hook for window events 'keyup' and 'keydown'
import { useEffect, useState } from 'react';
type Callback = (element?: string | number) => void
type TargetKey = string | number | Array<string|number>
const isNumber = (value: unknown): value is number => typeof value === 'number';
const isString = (value: unknown): value is string => typeof value === 'string';
const isNumberArray = (object: unknown): object is number[] =>
Array.isArray(object) && object.every(e => isNumber(e));
const isStringArray = (object: unknown): object is string[] =>
Array.isArray(object) && object.every(e => isString(e));
export default (targetKey: TargetKey, pressed: Callback, released?: Callback): void => {
const [keyPressed, setKeyPressed] = useState<boolean>(false);
const press = (element: string | number) => {
setKeyPressed(true);
if (pressed) pressed(element);
};
const release = (element: string | number) => {
setKeyPressed(false);
if (released) released(element);
};
const downHandler = ({ key, which }: KeyboardEvent) => {
if (keyPressed) return;
if (isStringArray(targetKey) && targetKey.includes(key))
press(key);
if (isNumberArray(targetKey) && targetKey.includes(which))
press(which);
if (isNumber(targetKey) && targetKey === which) press(which);
if (isString(targetKey) && targetKey === key) press(key);
};
const upHandler = ({ key, which }: KeyboardEvent) => {
if (!keyPressed) return;
if (isStringArray(targetKey) && targetKey.includes(key))
release(key);
if (isNumberArray(targetKey) && targetKey.includes(which))
release(which);
if (isNumber(targetKey) && targetKey === which) release(which);
if (isString(targetKey) && targetKey === key) release(key);
};
useEffect(() => {
window.addEventListener('keydown', downHandler);
window.addEventListener('keyup', upHandler);
return () => {
window.removeEventListener('keydown', downHandler);
window.removeEventListener('keyup', upHandler);
};
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment