Declarative Keyboard Shortcuts for React
React Shortcuts (version 2.1.0) is a library designed to manage keyboard shortcuts declaratively within React components. It provides a structured way to define application-wide and component-specific keymaps, which can include platform-specific variations and sequences. The library uses `mousetrap` (Combokeys) under the hood for robust key detection. Key differentiators include centralizing shortcut definitions and abstracting away boilerplate `addEventListener`/`removeEventListener` logic. However, the package is effectively abandoned, with its last release over 7 years ago and no recent development activity. It relies heavily on React's now-deprecated Legacy Context API (`getChildContext`), making it incompatible with modern React versions (17 and above).
Common errors
-
TypeError: Cannot read properties of undefined (reading 'shortcuts')
cause This error occurs when a `<Shortcuts>` component attempts to access the `shortcuts` object from the React context, but a parent component has not properly provided it using the legacy `getChildContext` and `childContextTypes` pattern, or the context mechanism has broken due to React version incompatibility.fixEnsure that a parent component (`App` in the quickstart) implements both `getChildContext` to return the `shortcutManager` and `childContextTypes` to declare its type (`PropTypes.object.isRequired`). Verify that your React version is compatible (React 16 or earlier). -
Warning: Legacy context API has been detected. These APIs are no longer supported in React 19+.
cause This is a warning from React itself, indicating that your application is using the deprecated `getChildContext` or `childContextTypes` APIs, which `react-shortcuts` relies upon.fixThis warning signals fundamental incompatibility with modern React. The primary 'fix' is to migrate away from `react-shortcuts` to a modern library that does not use the Legacy Context API. -
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined.
cause This error typically indicates that the `Shortcuts` component was not imported correctly or that `react-shortcuts` failed to initialize properly, leading to `Shortcuts` being `undefined` when React tries to render it.fixVerify that `import { Shortcuts } from 'react-shortcuts'` is correct and that the `react-shortcuts` package is installed and accessible in your environment. Check for any build or bundling issues that might prevent the component from being resolved.
Warnings
- breaking The library fundamentally relies on React's Legacy Context API (`getChildContext` and `childContextTypes`), which has been deprecated since React 16.3 and is removed entirely in React 19. Attempting to use this library with React 17+ will likely result in warnings or runtime errors related to this API.
- breaking The package's `peerDependencies` (`react` and `react-dom`) are explicitly limited to versions up to `^16`. Using it with React 17 or higher will lead to `npm` or `yarn` peer dependency warnings or installation failures, and likely runtime issues due to the reliance on removed React APIs.
- gotcha The `react-shortcuts` package is abandoned, with the last release over 7 years ago and no recent activity on its GitHub repository. This means there will be no future updates, bug fixes, security patches, or compatibility improvements for newer React versions or browser changes.
- gotcha The underlying `mousetrap` library often attaches global keyboard listeners. While `react-shortcuts` attempts to scope shortcuts to components, global listeners can still lead to conflicts with other libraries or unintended behaviors if not carefully managed, especially with the `global` prop on the `<Shortcuts>` component.
Install
-
npm install react-shortcuts -
yarn add react-shortcuts -
pnpm add react-shortcuts
Imports
- ShortcutManager
const ShortcutManager = require('react-shortcuts').ShortcutManagerimport { ShortcutManager } from 'react-shortcuts' - Shortcuts
const Shortcuts = require('react-shortcuts').Shortcutsimport { Shortcuts } from 'react-shortcuts'
Quickstart
import React from 'react';
import PropTypes from 'prop-types';
import { ShortcutManager, Shortcuts } from 'react-shortcuts';
const keymap = {
TODO_ITEM: {
MOVE_LEFT: 'left',
MOVE_RIGHT: 'right',
MOVE_UP: ['up', 'w'],
DELETE: {
osx: ['command+backspace', 'k'],
windows: 'delete',
linux: 'delete',
other: 'delete'
}
}
};
const shortcutManager = new ShortcutManager(keymap);
class App extends React.Component {
getChildContext() {
return { shortcuts: shortcutManager };
}
render() {
return (
<div>
<h1>React Shortcuts Demo</h1>
<TodoItem />
</div>
);
}
}
App.childContextTypes = {
shortcuts: PropTypes.object.isRequired
};
class TodoItem extends React.Component {
_handleShortcuts = (action, event) => {
switch (action) {
case 'MOVE_LEFT':
console.log('Moving left!');
break;
case 'MOVE_RIGHT':
console.log('Moving right!');
break;
case 'MOVE_UP':
console.log('Moving up!');
break;
case 'DELETE':
console.log('Deleting item!');
break;
default:
console.log(`Unhandled action: ${action}`);
}
event.preventDefault(); // Prevent default browser behavior
};
render() {
return (
<Shortcuts name='TODO_ITEM' handler={this._handleShortcuts}>
<div style={{ padding: '20px', border: '1px solid #ccc', margin: '10px' }}>
<h3>My Todo Item</h3>
<p>Try pressing 'left', 'right', 'up', or 'command+backspace' (macOS) / 'delete' (Windows/Linux).</p>
<p>Focus this area to activate shortcuts.</p>
<input type="text" placeholder="Type here, shortcuts should be ignored" />
</div>
</Shortcuts>
);
}
}
export default App;