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
- Keep all Drawer sub-parts inside `<Drawer>` (which renders the Root).
- If using portals, ensure the React subtree (not just DOM) stays under `<Drawer>`.
- 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
- Mount all Drawer parts under <Drawer> (the Root).
- For portals, keep the React subtree under <Drawer>.
- Add <Drawer> to story/test decorators.
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
- useCarousel must be used within a <Carousel />
- useChart must be used within a <ChartContainer />
- useProgress must be used within a Progress.
- useSidebar must be used within a SidebarProvider.
- useDrawer must be used within a Drawer.
AI-assisted analysis of shadcn-ui/ui@efac598707 (2026-08-12).
Data as JSON: /api/errors/3f524c3693bc33c7.
Report an issue: GitHub.