shadcn-ui/ui · error · Error

useDrawer must be used within a Drawer.

Error message

useDrawer must be used within a Drawer.

What it means

`useDrawer` reads `DrawerContext` (`createContext<DrawerContextProps | null>(null)`); `<Drawer>` (Vaul/aria primitive) supplies snap points, modal flag, swipe handle/direction. Drawer parts (DrawerContent/Trigger/Handle/Title/Description) rendered outside `<Drawer>` throw so behavior props are never null at consumers.

Source

Thrown at apps/v4/registry/bases/aria/ui/drawer.tsx:21

import * as React from "react"
import { Drawer as DrawerPrimitive } from "@base-ui/react/drawer"

import { cn } from "@/registry/bases/aria/lib/utils"

type DrawerContextProps = {
  hasSnapPoints: boolean
  modal: DrawerPrimitive.Root.Props["modal"]
  showSwipeHandle: boolean
  swipeDirection: NonNullable<DrawerPrimitive.Root.Props["swipeDirection"]>
}

const DrawerContext = React.createContext<DrawerContextProps | null>(null)

function useDrawer() {
  const context = React.useContext(DrawerContext)

  if (!context) {
    throw new Error("useDrawer must be used within a Drawer.")
  }

  return context
}

function Drawer({
  modal = true,
  showSwipeHandle = false,
  snapPoints,
  swipeDirection = "down",
  ...props
}: DrawerPrimitive.Root.Props & {
  showSwipeHandle?: boolean
}) {
  const hasSnapPoints = snapPoints != null && snapPoints.length > 0
  const contextValue = React.useMemo(
    () => ({ hasSnapPoints, modal, showSwipeHandle, swipeDirection }),
    [hasSnapPoints, modal, showSwipeHandle, swipeDirection]

View on GitHub (pinned to efac598707)

Solutions

  1. Keep all Drawer sub-parts inside `<Drawer>` (which renders the Root).
  2. If using portals, ensure the React subtree (not just DOM) stays under `<Drawer>`.
  3. Decorate tests/stories with `<Drawer>`.

Example fix

// before
<DrawerTrigger>Open</DrawerTrigger>
<Drawer>
  <DrawerContent>...</DrawerContent>
</Drawer>

// after
<Drawer>
  <DrawerTrigger>Open</DrawerTrigger>
  <DrawerContent>...</DrawerContent>
</Drawer>
Defensive patterns

Strategy: type-guard

Validate before calling

render(<Drawer><DrawerTrigger>Open</DrawerTrigger><DrawerContent>...</DrawerContent></Drawer>)

Type guard

import React from "react"
import { DrawerContext } from "@/registry/bases/aria/ui/drawer"
const insideDrawer = () => React.useContext(DrawerContext) != null

Try / catch

try { useDrawer() } catch (e) { if (e.message.includes("Drawer.")) {/*nest inside Drawer*/} throw e }

Prevention

When it happens

Trigger: Mounting `<DrawerContent />`, `<DrawerTrigger />`, or `<DrawerHandle />` outside `<Drawer>`. Common when composing a custom drawer or extracting the content into a separately mounted component.

Common situations: Reorganizing drawer markup; rendering DrawerContent in a portal whose React tree is outside Drawer; tests of individual parts.

Related errors


AI-assisted analysis of shadcn-ui/ui@efac598707 (2026-08-12). Data as JSON: /api/errors/3f524c3693bc33c7. Report an issue: GitHub.