React Context Menu
react-contextmenu is a React component library that provides accessible context menus (right-click menus) for web applications. It offers a declarative API to define context menu triggers and their associated menus, complete with individual menu items and dividers. The current stable version is 2.14.0. While there have been recent minor releases, the project is explicitly "Looking for maintainers," indicating a slowed or potentially halted development cadence without new contributors. Key differentiators include built-in accessibility support and a straightforward component-based API for integrating context menus into React applications, differentiating it from lower-level DOM manipulation or older jQuery-based solutions. It supports a wide range of browser versions, including older IE 11.
Common errors
-
Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components)...
cause Incorrect import of ContextMenu, MenuItem, or ContextMenuTrigger components, often due to CommonJS require() syntax or mixing named/default imports.fixUse named imports for all components: `import { ContextMenu, MenuItem, ContextMenuTrigger } from 'react-contextmenu';`. -
Warning: React does not recognize the `data` prop on a DOM element. If you intended to pass it to a custom component...
cause Attempting to pass the `data` prop directly to a standard HTML element within `ContextMenuTrigger` or `MenuItem` without proper handling, typically when `MenuItem` renders a custom component.fixThe `data` prop on `MenuItem` is intended to be accessed in the `onClick` handler. If you need to pass data to a custom component rendered by `MenuItem`, ensure your custom component accepts those props. For the trigger, wrap the native element in a custom component that consumes `data` or pass only valid HTML attributes. -
Menu does not appear on right-click, or appears and immediately disappears.
cause The `id` prop for `ContextMenuTrigger` and `ContextMenu` components do not match, or the `id` is not unique across the application, causing conflicts.fixVerify that `ContextMenuTrigger` and its corresponding `ContextMenu` share the exact same `id` string. Ensure this `id` is unique if you have multiple context menu pairs on the same page.
Warnings
- gotcha The project is explicitly "Looking for maintainers!!!". This indicates a potential lack of active development, slow response to issues, or eventual abandonment if new maintainers are not found. Consider its long-term viability for critical applications.
- breaking Version 2.12.0 was marked as 'deprecated' due to a regression. Users are advised to avoid this specific version.
- gotcha The `id` prop for `ContextMenuTrigger` and `ContextMenu` must be a globally unique identifier across your application, and consistent between the paired trigger and menu.
- gotcha The library has broad peer dependency ranges for `react` and `react-dom` (e.g., `^0.14.0 || ^15.0.0 || ^16.0.1`). While this allows flexibility, ensure your specific React version is compatible, especially with hooks-based components if you are using React 16.8+ features in your own application.
Install
-
npm install react-contextmenu -
yarn add react-contextmenu -
pnpm add react-contextmenu
Imports
- ContextMenu
const ContextMenu = require('react-contextmenu').ContextMenu;import { ContextMenu } from 'react-contextmenu'; - MenuItem
import MenuItem from 'react-contextmenu/MenuItem';
import { MenuItem } from 'react-contextmenu'; - ContextMenuTrigger
const { ContextMenuTrigger } = require('react-contextmenu');import { ContextMenuTrigger } from 'react-contextmenu';
Quickstart
import React from "react";
import ReactDOM from "react-dom";
import { ContextMenu, MenuItem, ContextMenuTrigger } from "react-contextmenu";
function handleClick(e, data) {
console.log(`Clicked on item with foo: ${data.foo}`);
}
function MyAppComponent() {
return (
<div>
<p>Right-click the box below to see a custom context menu.</p>
{/* NOTICE: id must be unique between EVERY <ContextMenuTrigger> and <ContextMenu> pair */}
{/* NOTICE: inside the pair, <ContextMenuTrigger> and <ContextMenu> must have the same id */}
<ContextMenuTrigger id="my_unique_menu_id">
<div style={{ border: '1px solid gray', padding: '20px', width: '200px', cursor: 'context-menu' }}>
Right click me!
</div>
</ContextMenuTrigger>
<ContextMenu id="my_unique_menu_id">
<MenuItem data={{ foo: 'item1_data' }} onClick={handleClick}>
Menu Item One
</MenuItem>
<MenuItem data={{ foo: 'item2_data' }} onClick={handleClick}>
Menu Item Two
</MenuItem>
<MenuItem divider />
<MenuItem data={{ foo: 'item3_data' }} onClick={handleClick}>
Menu Item Three (with separator)
</MenuItem>
<MenuItem disabled>
Disabled Item
</MenuItem>
</ContextMenu>
</div>
);
}
// Assuming a root element with id='root' in your HTML
ReactDOM.render(<MyAppComponent />, document.getElementById("root"));