janhq/jan · error · Error

DropDrawer components cannot be rendered outside the…

Error message

DropDrawer components cannot be rendered outside the DropDrawer Context

What it means

useDropDrawerContext reads DropDrawerContext created by the DropDrawer root component. DropDrawer sub-items (triggers, content, items) rely on that context for open/close state and mobile behavior; without it the hook throws. It prevents rendering dropdrawer pieces outside the root.

Solutions

  1. Wrap the dropdrawer sub-components in a <DropDrawer> root component.
  2. Move the sub-components back inside the DropDrawer JSX tree so context propagates.
  3. In tests/stories, wrap with a DropDrawer root before rendering items.
  4. If using React portals, keep the portal created inside the DropDrawer tree (portals still inherit React context).

Example fix

// before
<DropDrawerItem onClick={del}>Delete</DropDrawerItem>
// after
<DropDrawer>
  <DropDrawerTrigger>Actions</DropDrawerTrigger>
  <DropDrawerContent>
    <DropDrawerItem onClick={del}>Delete</DropDrawerItem>
  </DropDrawerContent>
</DropDrawer>
Defensive patterns

Strategy: type-guard

Validate before calling

const inDropDrawer = () => {
  const ctx = React.useContext(DropDrawerContext)
  return ctx !== null
}

Type guard

const ctx = React.useContext(DropDrawerContext)
if (ctx === null) {
  // render fallback or no-op instead of using context values
  return null
}

Try / catch

try {
  renderMenu()
} catch (e) {
  if (e instanceof Error && e.message.includes('DropDrawer Context')) {
    console.warn('DropDrawer item rendered without root; skipping')
  } else throw e
}

Prevention

When it happens

Trigger: Rendering <DropDrawerItem> or other dropdrawer sub-components without an ancestor <DropDrawer>, e.g. inside a portal, modal, or a list that renders items directly.

Common situations: Placing a DropDrawerItem inside a Tooltip/Popover portal that escapes the React tree context propagation; forgetting the root when refactoring menus; unit tests rendering items alone.

Related errors


AI-assisted analysis of janhq/jan@7205d770c1 (2026-09-17). Data as JSON: /api/errors/3f99c8d85698e584. Report an issue: GitHub.

Appendix: source

Thrown at web-app/src/components/ui/dropdrawer.tsx:35

  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuSeparator,
  DropdownMenuSub,
  DropdownMenuSubContent,
  DropdownMenuSubTrigger,
  DropdownMenuTrigger,
} from "./dropdown-menu";
import { useIsMobile } from "@/hooks/use-mobile";
import { cn } from "@/lib/utils";

const DropDrawerContext = React.createContext<{ isMobile: boolean }>({
  isMobile: false,
});

const useDropDrawerContext = () => {
  const context = React.useContext(DropDrawerContext);
  if (!context) {
    throw new Error(
      "DropDrawer components cannot be rendered outside the DropDrawer Context",
    );
  }
  return context;
};

function DropDrawer({
  children,
  ...props
}:
  | React.ComponentProps<typeof Drawer>
  | React.ComponentProps<typeof DropdownMenu>) {
  const isMobile = useIsMobile();
  const DropdownComponent = isMobile ? Drawer : DropdownMenu;

  return (
    <DropDrawerContext.Provider value={{ isMobile }}>
      <DropdownComponent

View on GitHub (pinned to 7205d770c1)