• Что бы вступить в ряды "Принятый кодер" Вам нужно:
    Написать 10 полезных сообщений или тем и Получить 10 симпатий.
    Для того кто не хочет терять время,может пожертвовать средства для поддержки сервеса, и вступить в ряды VIP на месяц, дополнительная информация в лс.

  • Пользаватели которые будут спамить, уходят в бан без предупреждения. Спам сообщения определяется администрацией и модератором.

  • Гость, Что бы Вы хотели увидеть на нашем Форуме? Изложить свои идеи и пожелания по улучшению форума Вы можете поделиться с нами здесь. ----> Перейдите сюда
  • Все пользователи не прошедшие проверку электронной почты будут заблокированы. Все вопросы с разблокировкой обращайтесь по адресу электронной почте : info@guardianelinks.com . Не пришло сообщение о проверке или о сбросе также сообщите нам.

Custom Hooks – useKeyPress

Lomanu4 Оффлайн

Lomanu4

Команда форума
Администратор
Регистрация
1 Мар 2015
Сообщения
16,069
Баллы
155
Adding keyboard shortcuts to a web application not only improves the user experience, but also makes certain tasks much faster and more intuitive.

The custom hook useKeyPress allows you to react to combinations like ⌘ + ArrowUp or single keys like F2, in a declarative and reusable way.


Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



A demo showing ⌘ + ArrowUp, ⌘ + ArrowDown, and F2 controlling a counter.
What does useKeyPress do?


This hook lets you:

  • Listen to multiple key combinations from an array, like ["⌘ + ArrowUp", "F2"].
  • Receive the main key pressed as an argument (e.g., "ArrowUp", "F2").
  • Use a single handler function to manage multiple shortcuts easily with if or switch.
Example: keyboard-controlled counter


import { useState } from "react";
import { useKeyPress } from "../core/hooks";

export const KeyPressComponent = () => {
const [counter, setCounter] = useState(0);

useKeyPress(["⌘ + ArrowDown", "⌘ + ArrowUp", "F2"], (key: string) => {
if (key === "ArrowDown")
setCounter((prev) => prev - 1);

if (key === "ArrowUp")
setCounter((prev) => prev + 1);

if (key === "F2")
setCounter(0);
});

return (
<div>
<h1>Key Press Example</h1>
<strong>{counter}</strong>
<p>
Press <em>⌘ + ArrowUp</em> to increase the counter
</p>
<p>
Press <em>⌘ + ArrowDown</em> to decrease the counter
</p>
<p>Press F2 to reset the counter</p>
</div>
);
};
How does it work internally?


Under the hood, useKeyPress listens for global keyboard events, normalizes combinations (e.g., "⌘ + ArrowUp" becomes "meta+arrowup"), and runs your callback only when an exact match is detected. You only get the main key in the callback ("ArrowUp", "F2", etc.), which keeps your component logic clean.

Here’s a full example of the hook implementation:


import { useEffect } from "react";

const useKeyPress = (keys: string[], callback: (key: string) => void) => {
useEffect(() => {
const handleKeyDown = (event: KeyboardEvent) => {
const pressedKey = event.key.toLowerCase();

const normalizedKeys = keys.map((key) =>
key
.toLowerCase()
.split(" + ")
.map((k) => k.trim())
);

const modifiers = {
control: event.ctrlKey,
shift: event.shiftKey,
alt: event.altKey,
meta: event.metaKey,
"⌘": event.ctrlKey,
ctrl: event.ctrlKey,
};

const modifierKeys = [
"control",
"shift",
"alt",
"meta",
"⌘",
"ctrl",
] as const;

for (const combination of normalizedKeys) {
const requiredModifiers = combination.filter((key) =>
modifierKeys.includes(key as (typeof modifierKeys)[number])
);
const requiredKeys = combination.filter(
(key) => !modifierKeys.includes(key as (typeof modifierKeys)[number])
);

const allModifiersMatch = requiredModifiers.every(
(mod) => modifiers[mod as keyof typeof modifiers]
);

const keyMatch = requiredKeys.includes(pressedKey);

if (keyMatch && allModifiersMatch) {
event.preventDefault();
callback(event.key);
return;
}
}
};

document.addEventListener("keydown", handleKeyDown, { capture: true });

return () => {
document.removeEventListener("keydown", handleKeyDown, { capture: true });
};
}, [keys, callback]);
};

export default useKeyPress;
✅ Benefits

  • ✅ Clear syntax: define multiple combinations in an array.
  • ✅ Clean-up included: automatically removes the listener.
  • ✅ Flexible: works across different platforms (Windows, macOS).
  • ✅ Declarative: avoids manual DOM event handling.
🧠 Final thoughts


Handling keyboard shortcuts doesn’t have to be messy. With useKeyPress, you can keep your components clean while adding power-user features that scale well.

Want to extend it?

  • Ignore events when inside an
  • Add debounce or throttle
  • Support dynamic combos via state
🙌 Thanks for reading


Thanks for reading this post — I hope it was helpful!

Feel free to leave a comment or suggestion below.
You're welcome to try, adapt, and improve the useKeyPress hook to fit your own use case.

Happy coding! 🎯


Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

 
Вверх Снизу