React Keyboard Shortcuts Hook

A custom React hook for handling keyboard shortcuts with TypeScript support


A reusable React hook for handling keyboard shortcuts with TypeScript support. This implementation includes support for modifier keys and prevents default behavior.

Types

types.ts
type KeyCombo = {
  key: string;
  ctrl?: boolean;
  shift?: boolean;
  alt?: boolean;
  meta?: boolean;
};
 
type Callback = (event: KeyboardEvent) => void;

Hook Implementation

useKeyboardShortcut.ts
import { useEffect, useCallback } from 'react';
 
export function useKeyboardShortcut(
  keyCombo: KeyCombo,
  callback: Callback,
  dependencies: any[] = []
) {
  const handleKeyDown = useCallback(
    (event: KeyboardEvent) => {
      const { key, ctrl, shift, alt, meta } = keyCombo;
 
      if (
        event.key.toLowerCase() === key.toLowerCase() &&
        event.ctrlKey === !!ctrl &&
        event.shiftKey === !!shift &&
        event.altKey === !!alt &&
        event.metaKey === !!meta
      ) {
        event.preventDefault();
        callback(event);
      }
    },
    [keyCombo, callback, ...dependencies]
  );
 
  useEffect(() => {
    window.addEventListener('keydown', handleKeyDown);
    return () => window.removeEventListener('keydown', handleKeyDown);
  }, [handleKeyDown]);
}

Usage Examples

Basic Usage

BasicExample.tsx
function SearchComponent() {
  useKeyboardShortcut(
    { key: 'k', ctrl: true },
    () => {
      // Open search modal
      console.log('Search shortcut triggered');
    }
  );
 
  return <div>Press Ctrl+K to search</div>;
}

Multiple Shortcuts

MultipleShortcuts.tsx
function EditorComponent() {
  // Save with confirmation
  useKeyboardShortcut(
    { key: 's', ctrl: true, shift: true },
    () => {
      console.log('Save with confirmation');
    }
  );
 
  // Quick save
  useKeyboardShortcut(
    { key: 's', ctrl: true },
    () => {
      console.log('Quick save');
    }
  );
 
  // Format code
  useKeyboardShortcut(
    { key: 'f', ctrl: true, shift: true },
    () => {
      console.log('Format code');
    }
  );
 
  return (
    <div>
      <p>Available shortcuts:</p>
      <ul>
        <li>Ctrl+Shift+S: Save with confirmation</li>
        <li>Ctrl+S: Quick save</li>
        <li>Ctrl+Shift+F: Format code</li>
      </ul>
    </div>
  );
}

With Dependencies

WithDependencies.tsx
function SearchableList() {
  const [searchQuery, setSearchQuery] = useState('');
 
  useKeyboardShortcut(
    { key: 'f', ctrl: true },
    () => {
      // Focus search input
      document.getElementById('search-input')?.focus();
    },
    [searchQuery] // Recreate shortcut when searchQuery changes
  );
 
  return (
    <div>
      <input
        id="search-input"
        type="text"
        value={searchQuery}
        onChange={(e) => setSearchQuery(e.target.value)}
        placeholder="Search..."
      />
      {/* List items */}
    </div>
  );
}

Imports

imports.ts
import { useEffect, useCallback } from 'react';

Features:

  • TypeScript support with proper type definitions
  • Support for modifier keys (Ctrl, Shift, Alt, Meta)
  • Prevents default browser behavior
  • Cleanup on component unmount
  • Dependency array for callback updates
  • Case-insensitive key matching
  • Multiple shortcut support
  • Clean and reusable implementation