Routing
NextUI Components such as Tabs, Listbox, Dropdown and many others offer the flexibility to be rendered as HTML links. Explore this page to learn how to integrate them with client side routing.
Introduction
By default, links perform native browser navigation when they are interacted with. However, many apps and
frameworks use client side routers to avoid a full page reload when navigating between pages. The NextUIProvider
component configures all NextUI components within it to navigate using the client side router you provide.
Set this up once in the root of your app, and any NextUI component with the href prop will automatically navigate using your router.
NextUIProvider Setup
The NextUIProvider
accepts a prop called navigate
. This should be set to a function received from your
router for performing a client side navigation programmatically. The following example shows the general
pattern. Framework-specific examples are shown below.
import * as React from "react";// 1. import `NextUIProvider` componentimport {NextUIProvider} from "@nextui-org/react";function App() { const navigate = useNavigateFromYourRouter(); // 2. Add the `navigate` function to the `NextUIProvider` return ( <NextUIProvider navigate={navigate}> <YourApplication /> </NextUIProvider> );}
const navigate = useNavigateFromYourRouter();// 2. Add the `navigate` function to the `NextUIProvider`return (<NextUIProvider navigate={navigate}><YourApplication /></NextUIProvider>);}
Next.js
App Router
Go to your app/providers.tsx
or app/providers.jsx
(create it if it doesn't exist) and add the
useRouter
hook from next/navigation
, it returns a router object that can be used to perform navigation.
Add the useRouter
// app/providers.tsx"use client"import {NextUIProvider} from "@nextui-org/react";import {useRouter} from "next/navigation"export function Providers({children}: { children: React.ReactNode }) {const router = useRouter();return (<NextUIProvider navigate={router.push}>{children}</NextUIProvider>)}
Add Provider to Root
Now, Go to your root
layout page and wrap it with the NextUIProvider
:
// app/layout.tsximport {Providers} from "./providers";export default function RootLayout({children}: { children: React.ReactNode }) { return ( <html lang="en" className="dark"> <body> <Providers> {children} </Providers> </body> </html> );}
return (<html lang="en" className="dark"><body><Providers>{children}</Providers></body></html>);}
Note: Skip this step if you already set up the
NextUIProvider
in your app.
Add useHref (Optional)
If you are using the Next.js basePath setting, you'll need to configure an environment variable to access it.
// next.config.jsconst basePath = "...";const nextConfig = {basePath,env: {BASE_PATH: basePath}};
Then, provide a custom useHref
function to prepend it to the href for all links.
// app/providers.tsx"use client"import {NextUIProvider} from "@nextui-org/react";import {useRouter} from "next/navigation"export function Providers({children}: { children: React.ReactNode }) {const router = useRouter();const useHref = (href: string) => process.env.BASE_PATH + href;return (<NextUIProvider navigate={router.push} useHref={useHref}>{children}</NextUIProvider>)}
Pages Router
Go to pages/_app.js
or pages/_app.tsx
(create it if it doesn't exist) and add theuseRouter
hook
from next/router
, it returns a router object that can be used to perform navigation.
// pages/_app.tsximport type { AppProps } from "next/app";import {NextUIProvider} from "@nextui-org/react";import {useRouter} from "next/router";function MyApp({ Component, pageProps }: AppProps) { const router = useRouter(); return ( <NextUIProvider navigate={router.push}> <Component {...pageProps} /> </NextUIProvider> )}
const router = useRouter();return (<NextUIProvider navigate={router.push}><Component {...pageProps} /></NextUIProvider>)}export default MyApp;
When using the basePath configuration option, provide a useHref
option to the router passed to Provider to prepend it to links automatically.
// pages/_app.tsximport type { AppProps } from "next/app";import {NextUIProvider} from "@nextui-org/react";import {useRouter} from "next/router";function MyApp({ Component, pageProps }: AppProps) { const router = useRouter(); const useHref = (href: string) => router.basePath + href; return ( <NextUIProvider navigate={router.push} useHref={useHref}> <Component {...pageProps} /> </NextUIProvider> )}
const router = useRouter();const useHref = (href: string) => router.basePath + href;return (<NextUIProvider navigate={router.push} useHref={useHref}><Component {...pageProps} /></NextUIProvider>)}export default MyApp;
React Router
The useNavigate
hook from react-router-dom
returns a navigate
function that can be used to perform navigation.
The useHref
hook can also be provided if you're using React Router's basename
option. Ensure that the component that calls useNavigate and renders Provider is inside the router component (e.g. BrowserRouter
) so that it has access to React Router's internal context. The React Router <Routes>
element should also be defined inside <NextUIProvider>
so that links inside the rendered routes have access to the router.
Go to the App
file commonly called App.jsx
or App.tsx
, add the useNavigate
hook and pass the
navigate
function to the NextUIProvider
:
// App.tsx or App.jsximport {BrowserRouter, useNavigate, useHref} from "react-router-dom";import {NextUIProvider} from "@nextui-org/react";function App() { const navigate = useNavigate(); return ( <NextUIProvider navigate={navigate} useHref={useHref}> {/* Your app here... */} <Routes> <Route path="/" element={<HomePage />} /> {/* ... */} </Routes> </NextUIProvider> );}
const navigate = useNavigate();return (<NextUIProvider navigate={navigate} useHref={useHref}>{/* Your app here... */}<Routes><Route path="/" element={<HomePage />} />{/* ... */}</Routes></NextUIProvider>);}// main.tsx or main.jsxReactDOM.createRoot(document.getElementById("root")).render(<React.StrictMode><BrowserRouter><App /></BrowserRouter></React.StrictMode>,)
Ensure that the component that calls useNavigate
and renders NextUIProvider
is inside the router
component (e.g. BrowserRouter
) so that it has access to React Router's internal context. The React Router <Routes>
element should also be defined inside NextUIProvider
so that links inside the rendered routes have access
to the router.
Remix
Remix uses React Router under the hood, so the same useNavigate
and useHref
hook described above also works in Remix
apps. NextUIProvider
should be rendered at the root
of each page that includes NextUI components, or in
app/root.tsx
to add it to all pages. See the Remix docs
for more details.
// app/root.tsximport {useNavigate, useHref, Outlet} from "@remix-run/react";import {NextUIProvider} from "@nextui-org/react";export default function App() { const navigate = useNavigate(); return ( <html lang="en"> <head> {/* ... */} </head> <body> <NextUIProvider navigate={navigate} useHref={useHref}> <Outlet /> </NextUIProvider> {/* ... */} </body> </html> );}
const navigate = useNavigate();return (<html lang="en"><head>{/* ... */}</head><body><NextUIProvider navigate={navigate} useHref={useHref}><Outlet /></NextUIProvider>{/* ... */}</body></html>);}
TanStack
To use TanStack Router with NextUI, render NextUI's RouterProvider inside your root route. Use router.navigate
in the navigate
prop, and router.buildLocation
in the useHref
prop.
// app/root.tsximport {NextUIProvider} from "@nextui-org/react";function RootRoute() { let router = useRouter(); return ( <NextUIProvider navigate={(to, options) => router.navigate({ to, ...options })} useHref={(to) => router.buildLocation({ to }).href} > {/* You app here... */} </NextUIProvider> );}
let router = useRouter();return (<NextUIProvidernavigate={(to, options) => router.navigate({ to, ...options })}useHref={(to) => router.buildLocation({ to }).href}>{/* You app here... */}</NextUIProvider>);}
Usage examples
Now that you have set up the NextUIProvider
in your app, you can use the href
prop in the Tabs
,
Listbox
and Dropdown
items to navigate between pages.
The Link component will also use the navigate
function from the
NextUIProvider
to navigate between pages.
import { Tabs, Tab, Listbox, ListboxItem, Dropdown, DropdownTrigger, DropdownMenu, DropdownItem, Button, Link,} from "@nextui-org/react";
Tabs,Tab,Listbox,ListboxItem,Dropdown,DropdownTrigger,DropdownMenu,DropdownItem,Button,Link,} from "@nextui-org/react";function App() { return ( <> <Tabs aria-label="Navigation"> <Tab key="home" href="/home">Home</Tab> <Tab key="about" href="/about">About</Tab> </Tabs> <Listbox aria-label="Navigation"> <ListboxItem key="home" href="/home">Home</ListboxItem> <ListboxItem key="about" href="/about">About</ListboxItem> </Listbox> <Dropdown> <DropdownTrigger> <Button>Open</Button> </DropdownTrigger> <DropdownMenu aria-label="Navigation"> <DropdownItem key="home" href="/home">Home</DropdownItem> <DropdownItem key="about" href="/about">About</DropdownItem> </DropdownMenu> </Dropdown> <Link href="/home">Home</Link> <Link href="/about">About</Link> </> );}
return (<><Tabs aria-label="Navigation"><Tab key="home" href="/home">Home</Tab><Tab key="about" href="/about">About</Tab></Tabs><Listbox aria-label="Navigation"><ListboxItem key="home" href="/home">Home</ListboxItem><ListboxItem key="about" href="/about">About</ListboxItem></Listbox><Dropdown><DropdownTrigger><Button>Open</Button></DropdownTrigger><DropdownMenu aria-label="Navigation"><DropdownItem key="home" href="/home">Home</DropdownItem><DropdownItem key="about" href="/about">About</DropdownItem></DropdownMenu></Dropdown><Link href="/home">Home</Link><Link href="/about">About</Link></>);}