mantinedev/mantine · error · Error

Menu.ContextMenu component children should be an element or

Error message

Menu.ContextMenu component children should be an element or a component that accepts ref. Fragments, strings, numbers and other primitive values are not supported

What it means

Menu.ContextMenu attaches long-press/contextmenu handlers and a ref to its single child so a menu can open on right-click/long-press. If getSingleElementChild finds no single element (fragment, string, number, empty), there is nothing to bind to and it throws.

Source

Thrown at packages/@mantine/core/src/components/Menu/MenuContextMenu/MenuContextMenu.tsx:23

import { useMenuContext } from '../Menu.context';

export interface MenuContextMenuProps {
  /** Element that opens the menu when right-clicked. Menu dropdown is positioned at the cursor. The trigger element must not call `event.preventDefault()` in its own `onContextMenu` handler, otherwise the native context menu is not suppressed. */
  children: React.ReactNode;

  /** If set, the right-click trigger is disabled and the browser's default context menu is shown */
  disabled?: boolean;

  /** Delay in ms before a touch long-press opens the dropdown on touch devices, `500` by default */
  longPressDelay?: number;
}

export function MenuContextMenu(props: MenuContextMenuProps) {
  const { children, disabled, longPressDelay } = useProps('MenuContextMenu', null, props);

  const child = getSingleElementChild(children);
  if (!child) {
    throw new Error(
      'Menu.ContextMenu component children should be an element or a component that accepts ref. Fragments, strings, numbers and other primitive values are not supported'
    );
  }

  const ctx = useMenuContext();
  const popoverCtx = usePopoverContext();

  const handlers = useContextMenuHandlers({
    childProps: child.props as any,
    disabled: disabled || popoverCtx.disabled,
    opened: ctx.opened,
    longPressDelay,
    setReference: popoverCtx.reference as unknown as (node: object) => void,
    open: () => ctx.openDropdown(),
  });

  return cloneElement(child, handlers as any);
}

View on GitHub (pinned to 8a284e2c2c)

Solutions

  1. Pass exactly one element (e.g. the row/list item component) as the child
  2. Ensure that component forwards refs to its root DOM node
  3. Avoid conditional fragments around the target element

Example fix

// before
<Menu.ContextMenu><>{item.name}</></Menu.ContextMenu>

// after
<Menu.ContextMenu><TableRow>{item.name}</TableRow></Menu.ContextMenu>
Defensive patterns

Strategy: type-guard

Validate before calling

// Ensure Menu.ContextMenu wraps exactly one ref-forwarding element (e.g. the row component)

Type guard

const hasSingleElementChild = (children: React.ReactNode): boolean =>
  Array.isArray(children)
    ? children.filter(Boolean).length === 1 && isElement(children.find(Boolean))
    : isElement(children);

Prevention

When it happens

Trigger: Child of Menu.ContextMenu is a fragment, primitive, multiple siblings, or a non-ref-forwarding component. Also note this component must sit inside Menu/Popover context, otherwise a context error follows.

Common situations: Making table rows or list items context-menu targets but wrapping them in fragments, or passing text directly as the trigger.

Related errors


AI-assisted analysis of mantinedev/mantine@8a284e2c2c (2026-08-28). Data as JSON: /api/errors/12adc8e33cf799ff. Report an issue: GitHub.