30% offEnding soon
useHotkeysLoading saved progress…

useHotkeys

useHotkeys binds a keyboard shortcut — a chord like ctrl+k or cmd+shift+p — to a handler that runs only when exactly that combination is pressed. Command palettes, editors, and dashboards lean on shortcuts, and getting them right is subtler than a keydown listener looks: the hook has to match the modifier keys exactly, and it has to stay out of the way while the user is typing. You will implement it in the shape popularized by react-hotkeys-hook.

Signature

function useHotkeys(
  keys: string | string[],           // 'ctrl+k', 'cmd+shift+p', or ['ctrl+k', 'cmd+k']
  handler: (event: KeyboardEvent) => void,
  options?: {
    enableOnFormTags?: boolean;      // default false — do NOT fire while typing in a field
    preventDefault?: boolean;        // default false — call event.preventDefault() on a match
  },
): void;

The hook returns nothing; it wires up a keydown listener as a side effect and cleans it up on unmount.

Examples

function App() {
  const [open, setOpen] = useState(false);
  // Open the command palette on Ctrl+K.
  useHotkeys('ctrl+k', () => setOpen(true));
  return open ? <Palette onClose={() => setOpen(false)} /> : null;
}
// useHotkeys('ctrl+k', handler)
// keydown  ctrl+k          -> handler fires
// keydown  ctrl+shift+k    -> ignored (an extra modifier is held)
// keydown  k               -> ignored (ctrl is required)
// keydown  k  (in an input)-> ignored (that keystroke is the user typing)

Notes

  • Exact match — a ctrl+k binding fires only on ctrl+k. Every required modifier must be present and every un-required modifier must be absent, so ctrl+shift+k does not trigger it.
  • Modifiers and aliases — recognize ctrl/control, shift, alt/option, and meta/cmd/command, joined with +. Decide whether to support a mod alias (Cmd on macOS, Ctrl elsewhere) and justify the platform detection it needs.
  • Do not fight typing — by default the shortcut must not fire while focus is in an input, textarea, select, or contentEditable element, or a bare-letter shortcut would eat the user's keystrokes. enableOnFormTags opts back in.
  • Fire once per press — call the handler on keydown. This binds a chord to an action; it does not report whether a key is being held. For that held-key boolean, see useKeyPress.
  • Always the latest handler — callers pass a fresh inline function every render. Call the most recent one without tearing down and re-adding the listener on each render.
  • Arrays of combos — accept either a single combo string or an array of combos that share the one handler.