useDrawer

useDrawer returns the full state of the nearest <Drawer> navigator, for building a completely custom sidebar.

<Drawer> already renders headless on web by default (just the focused screen, no sidebar); reach for useDrawer when you want to render the sidebar yourself. See the headless web navigators guide for the full picture.

Drawer ships from one/drawer to keep bundle size down for apps that don’t use it. useDrawer ships from one directly.

Usage

Place your component as a child of <Drawer>. It replaces the headless default on web and is ignored on native, so the same layout file works everywhere:

// app/_layout.tsx, works on both platforms
import { Drawer } from 'one/drawer'
import { Link, useDrawer } from 'one'
function WebDrawerLayout() {
const { screens, focused, isOpen, close, toggle } = useDrawer()
return (
<>
<button onClick={toggle}>Menu</button>
{isOpen && (
<nav>
{screens.map((screen) => (
<Link key={screen.key} href={screen.href} onPress={close}>
{screen.options.drawerLabel ?? screen.options.title ?? screen.name}
</Link>
))}
</nav>
)}
{focused.element}
</>
)
}
export default function Layout() {
return (
<Drawer>
<Drawer.Screen name="index" options={{ drawerLabel: 'Home' }} />
<Drawer.Screen name="settings" options={{ drawerLabel: 'Settings' }} />
<WebDrawerLayout />
</Drawer>
)
}

Return value

PropertyTypeDescription
screensScreenEntry[]Every screen in the drawer.
focusedScreenEntryThe currently focused screen.
isOpenbooleanWhether the drawer is currently open.
open()() => voidOpen the drawer.
close()() => voidClose the drawer.
toggle()() => voidToggle the drawer.

ScreenEntry is the same shape useStack returns: key, name, params, href, isFocused, keepMounted, options, element.

Edit this page on GitHub.