mirror of
https://github.com/nextui-org/nextui.git
synced 2025-12-08 19:26:11 +00:00
docs: add forms guide (#3822)
This commit is contained in:
parent
d51d3546cd
commit
ad79545d95
@ -19,7 +19,7 @@ const paddingLeftByLevel: Record<number, string> = {
|
||||
1: "pl-0",
|
||||
2: "pl-0",
|
||||
3: "pl-3",
|
||||
4: "pl-3",
|
||||
4: "pl-6",
|
||||
};
|
||||
|
||||
export const DocsToc: FC<DocsTocProps> = ({headings}) => {
|
||||
|
||||
@ -37,6 +37,12 @@
|
||||
"keywords": "client side routing, routing, browser routing, nextui, next.js router, react router, remix router",
|
||||
"path": "/docs/guide/routing.mdx"
|
||||
},
|
||||
{
|
||||
"key": "form",
|
||||
"title": "Forms",
|
||||
"keywords": "forms, form validation, nextui",
|
||||
"path": "/docs/guide/form.mdx"
|
||||
},
|
||||
{
|
||||
"key": "upgrade-to-v2",
|
||||
"title": "Upgrade to v2",
|
||||
|
||||
416
apps/docs/content/docs/guide/form.mdx
Normal file
416
apps/docs/content/docs/guide/form.mdx
Normal file
@ -0,0 +1,416 @@
|
||||
---
|
||||
title: Forms
|
||||
description: Learn how to handle forms in NextUI.
|
||||
---
|
||||
|
||||
# Forms
|
||||
|
||||
NextUI form components are designed to be flexible and function as HTML form elements. They support form data submission, custom validation, real-time validation, and offer an accessible UI.
|
||||
|
||||
<CarbonAd/>
|
||||
|
||||
## Labels and help text
|
||||
|
||||
Accessible forms require clear and descriptive labels. NextUI components allow you to add labels to each field through the label prop.
|
||||
You can also display help text such as descriptions or error messages.
|
||||
|
||||
```tsx
|
||||
import {Input} from "@nextui-org/react";
|
||||
|
||||
<Input
|
||||
type="password"
|
||||
label="Password"
|
||||
description="Password must be at least 8 characters."
|
||||
/>
|
||||
```
|
||||
|
||||
Labels should usually be visually displayed, but in rare cases, you need to provide an aria-label or aria-labelledby attribute to identify the element for screen readers.
|
||||
|
||||
## Submitting data
|
||||
|
||||
How you submit form data depends on your framework, application, and server.
|
||||
By default, HTML forms are submitted via a full-page refresh in the browser.
|
||||
You can call `preventDefault` in the `onSubmit` event to handle form data submission via an API.
|
||||
|
||||
### Uncontrolled forms
|
||||
|
||||
A simple way to get form data is to use `FormData` API. You can send this data to a backend API or convert it into a JavaScript object using [`Object.fromEntries`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/fromEntries).
|
||||
Each field should have a `name` prop to identify it, and the values will be serialized as strings by the browser.
|
||||
|
||||
```tsx
|
||||
import {Button, Form, Input} from "@nextui-org/react";
|
||||
|
||||
function Example() {
|
||||
const [submitted, setSubmitted] = React.useState(null);
|
||||
|
||||
const onSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
||||
// Prevent default browser page refresh.
|
||||
e.preventDefault();
|
||||
|
||||
// Get form data as an object.
|
||||
const data = Object.fromEntries(new FormData(e.currentTarget));
|
||||
|
||||
// Submit data to your backend API. (currently logged to the console)
|
||||
console.log("Form submitted:", data);
|
||||
};
|
||||
|
||||
return (
|
||||
<Form onSubmit={onSubmit}>
|
||||
<Input label="Name" name="name" />
|
||||
<Button type="submit">Submit</Button>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Controlled forms
|
||||
|
||||
NextUI form components are uncontrolled by default, but if you need to manage state in real-time, you can use the `useState` hook to make the component controlled.
|
||||
|
||||
```tsx
|
||||
import {Button, Form, Input} from "@nextui-org/react";
|
||||
|
||||
function Example() {
|
||||
const [name, setName] = React.useState("");
|
||||
const onSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
// Submit data to your backend API.
|
||||
alert(name);
|
||||
};
|
||||
|
||||
return (
|
||||
<Form onSubmit={onSubmit}>
|
||||
<Input value={name} onValueChange={setName} />
|
||||
<Button type="submit">Submit</Button>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Validation
|
||||
|
||||
Form validation is crucial for ensuring that users enter the correct data.
|
||||
NextUI supports native HTML constraint validation and allows for custom validation and real-time validation.
|
||||
|
||||
### Built-in validation
|
||||
|
||||
NextUI form components support [native HTML validation](https://developer.mozilla.org/docs/Web/HTML/Constraint_validation) attributes like `isRequired` and `minLength`.
|
||||
These constraints are checked by the browser when the user commits changes (e.g., onBlur) or submits the form.
|
||||
You can display validation errors with custom styles instead of the browser's default UI.
|
||||
|
||||
```tsx
|
||||
import {Button, Form, Input} from "@nextui-org/react";
|
||||
|
||||
<Form validationBehavior="native">
|
||||
<Input name="email" type="email" isRequired />
|
||||
<Button type="submit">Submit</Button>
|
||||
</Form>
|
||||
```
|
||||
|
||||
To enable native validation, set `validationBehavior="native"`.
|
||||
By default, `validationBehavior="aria"` is set, which only marks the field as required or invalid for assistive technologies, without preventing form submission.
|
||||
You can change the form defaults for your entire app using [NextUI Provider](/docs/api-references/nextui-provider).
|
||||
|
||||
### Customizing error messages
|
||||
|
||||
By default, error messages are provided by the browser.
|
||||
You can customize these messages by providing a function to the `errorMessage` prop.
|
||||
|
||||
```tsx {9-19}
|
||||
import {Button, Form, Input} from "@nextui-org/react";
|
||||
|
||||
<Form validationBehavior="native">
|
||||
<Input
|
||||
label="Number"
|
||||
isRequired
|
||||
min={0}
|
||||
max={100}
|
||||
errorMessage={(validationResult) => {
|
||||
if (validationResult.validationDetails.rangeOverflow) {
|
||||
return "Value is too high";
|
||||
}
|
||||
if (validationResult.validationDetails.rangeUnderflow) {
|
||||
return "Value is too low";
|
||||
}
|
||||
if (validationResult.validationDetails.valueMissing) {
|
||||
return "Value is required";
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Button type="submit">Submit</Button>
|
||||
</Form>
|
||||
```
|
||||
|
||||
> **Note**: The default error messages are localized by the browser based on the browser/operating system language settings. The [locale setting in NextUI Provider](/docs/api-references/nextui-provider#props) does not affect validation errors.
|
||||
|
||||
### Custom validation
|
||||
|
||||
In addition to built-in constraints, you can provide a function to the `validate` prop to support custom validation.
|
||||
|
||||
```tsx {7-11}
|
||||
import {Button, Form, Input} from "@nextui-org/react";
|
||||
|
||||
<Form>
|
||||
<Input
|
||||
label="Number"
|
||||
type="number"
|
||||
validate={(value) => {
|
||||
if (value < 0 || value > 100) {
|
||||
return "Value must be between 0 and 100";
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Button type="submit">Submit</Button>
|
||||
</Form>
|
||||
```
|
||||
|
||||
### Realtime validation
|
||||
|
||||
If you want to display validation errors while the user is typing, you can control the field value and use the `isInvalid` prop along with the `errorMessage` prop.
|
||||
|
||||
```tsx {22-31}
|
||||
import {Input} from "@nextui-org/react";
|
||||
|
||||
export function Example() {
|
||||
const [password, setPassword] = React.useState("");
|
||||
const errors: string[] = [];
|
||||
|
||||
if (password.length < 8) {
|
||||
errors.push("Password must be 8 characters or more.");
|
||||
}
|
||||
if ((password.match(/[A-Z]/g) ?? []).length < 2) {
|
||||
errors.push("Password must include at least 2 upper case letters");
|
||||
}
|
||||
if ((password.match(/[^a-z]/gi) ?? []).length < 2) {
|
||||
errors.push("Password must include at least 2 symbols.");
|
||||
}
|
||||
|
||||
return (
|
||||
<Input
|
||||
label="Name"
|
||||
value={password}
|
||||
onValueChange={setPassword}
|
||||
isInvalid={errors.length > 0}
|
||||
errorMessage={() => (
|
||||
<ul>
|
||||
{errors.map((error, i) => (
|
||||
<li key={i}>{error}</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Server validation
|
||||
|
||||
Client-side validation provides immediate feedback, but you should also validate data on the server to ensure accuracy and security.
|
||||
NextUI allows you to display server-side validation errors by using the `validationErrors` prop in the `Form` component.
|
||||
This prop should be an object where each key is the field `name` and the value is the error message.
|
||||
|
||||
```tsx {15}
|
||||
import {Button, Form, Input} from "@nextui-org/react";
|
||||
|
||||
function Example() {
|
||||
const [errors, setErrors] = React.useState({});
|
||||
const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
|
||||
const data = Object.fromEntries(new FormData(e.currentTarget));
|
||||
const result = await callServer(data);
|
||||
|
||||
setErrors(result.errors);
|
||||
};
|
||||
|
||||
return (
|
||||
<Form validationErrors={errors} onSubmit={onSubmit}>
|
||||
<Input label="Username" name="username" />
|
||||
<Input label="Password" name="password" type="password" />
|
||||
<Button type="submit">Submit</Button>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
|
||||
// Fake server used in this example.
|
||||
function callServer(data) {
|
||||
return {
|
||||
errors: {
|
||||
username: "Sorry, this username is taken.",
|
||||
},
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
#### Schema validation
|
||||
|
||||
NextUI supports errors from schema validation libraries like Zod.
|
||||
You can use Zod's `flatten` method to get error messages for each field and return them as part of the server response.
|
||||
|
||||
```tsx
|
||||
// In your server.
|
||||
import {z} from "zod";
|
||||
|
||||
const schema = z.object({
|
||||
name: z.string().min(1),
|
||||
age: z.coerce.number().positive()
|
||||
});
|
||||
|
||||
function handleRequest(formData: FormData) {
|
||||
const result = schema.safeParse(
|
||||
Object.fromEntries(formData)
|
||||
);
|
||||
if (!result.success) {
|
||||
return {
|
||||
errors: result.error.flatten().fieldErrors
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
errors: {}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
#### React Server Actions
|
||||
|
||||
[Server Actions](https://react.dev/reference/rsc/server-actions) that allows seamless form submission to the server and retrieval of results.
|
||||
The [`useActionState`](https://react.dev/reference/react/useActionState) hook can be used to get the result of server actions (such as errors) after submitting a form.
|
||||
|
||||
```tsx {14}
|
||||
// app/add-form.tsx
|
||||
"use client";
|
||||
|
||||
import {useActionState} from "react";
|
||||
import {Button, Input, Label} from "@nextui-org/react";
|
||||
import {createTodo} from "@/app/actions";
|
||||
|
||||
export function AddForm() {
|
||||
const [{ errors }, formAction] = useActionState(createTodo, {
|
||||
errors: {}
|
||||
});
|
||||
|
||||
return (
|
||||
<Form action={formAction} validationErrors={errors}>
|
||||
<Input name="todo" label="Task" />
|
||||
<Button type="submit">Add</Button>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
```ts
|
||||
// app/actions.ts
|
||||
"use server";
|
||||
|
||||
export async function createTodo(
|
||||
prevState: any,
|
||||
formData: FormData
|
||||
) {
|
||||
try {
|
||||
// Create the todo.
|
||||
} catch (err) {
|
||||
return {
|
||||
errors: {
|
||||
todo: "Invalid todo."
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Remix
|
||||
|
||||
Remix actions handle form submissions on the server.
|
||||
You can use the [`useSubmit`](https://remix.run/docs/en/main/hooks/use-submit) hook to submit form data to the server and the [`useActionData`](https://remix.run/docs/en/main/hooks/use-action-data) hook to retrieve validation errors from the server.
|
||||
|
||||
```tsx {18}
|
||||
// app/routes/signup.tsx
|
||||
import type {ActionFunctionArgs} from "@remix-run/node";
|
||||
import {useActionData, useSubmit} from "@remix-run/react";
|
||||
import {Button, Form, Input} from "@nextui-org/react";
|
||||
|
||||
export default function SignupForm() {
|
||||
const [errors, setErrors] = React.useState({});
|
||||
const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
|
||||
const data = Object.fromEntries(new FormData(e.currentTarget));
|
||||
const result = await callServer(data);
|
||||
|
||||
setErrors(result.errors);
|
||||
};
|
||||
|
||||
return (
|
||||
<Form validationErrors={errors} onSubmit={onSubmit}>
|
||||
<Input label="Username" name="username" />
|
||||
<Input label="Password" name="password" type="password" />
|
||||
<Button type="submit">Submit</Button>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
|
||||
export async function action(
|
||||
{ request }: ActionFunctionArgs
|
||||
) {
|
||||
try {
|
||||
// Validate data and perform action...
|
||||
} catch (err) {
|
||||
return {
|
||||
errors: {
|
||||
username: "Sorry, this username is taken."
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Form libraries
|
||||
|
||||
In most cases, the built-in validation features of NextUI are sufficient. However, if you're building more complex forms or integrating NextUI components into an existing form, you can use a form library like React Hook Form or Formik.
|
||||
|
||||
### React Hook Form
|
||||
|
||||
You can integrate NextUI components using [`Controller`](https://react-hook-form.com/docs/usecontroller/controller).
|
||||
`Controller` allows you to manage field values and validation errors, and reflect the validation result in NextUI components.
|
||||
|
||||
```tsx
|
||||
import {Controller, useForm} from "react-hook-form";
|
||||
import {Button, Input, Label} from "@nextui-org/react";
|
||||
|
||||
function App() {
|
||||
const { handleSubmit, control } = useForm({
|
||||
defaultValues: {
|
||||
name: ""
|
||||
}
|
||||
});
|
||||
const onSubmit = (data) => {
|
||||
// Call your API here.
|
||||
};
|
||||
|
||||
return (
|
||||
<Form onSubmit={handleSubmit(onSubmit)}>
|
||||
<Controller
|
||||
control={control}
|
||||
name="name"
|
||||
render={({field: {name, value, onChange, onBlur, ref}, fieldState: {invalid, error}}) => (
|
||||
<Input
|
||||
ref={ref}
|
||||
isRequired
|
||||
errorMessage={error?.message}
|
||||
isInvalid={invalid}
|
||||
label="Name"
|
||||
name={name}
|
||||
value={value}
|
||||
onBlur={onBlur}
|
||||
onChange={onChange}
|
||||
/>
|
||||
)}
|
||||
rules={{required: "Name is required."}}
|
||||
/>
|
||||
<Button type="submit">Submit</Button>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
```
|
||||
@ -45,7 +45,7 @@ function App() {
|
||||
|
||||
<Spacer y={2} />
|
||||
|
||||
## Next.js
|
||||
## Next.js
|
||||
|
||||
### App Router
|
||||
|
||||
@ -58,10 +58,10 @@ Go to your `app/providers.tsx` or `app/providers.jsx` (create it if it doesn't e
|
||||
|
||||
```tsx {8}
|
||||
// app/providers.tsx
|
||||
'use client'
|
||||
"use client"
|
||||
|
||||
import {NextUIProvider} from '@nextui-org/react';
|
||||
import {useRouter} from 'next/navigation'
|
||||
import {NextUIProvider} from "@nextui-org/react";
|
||||
import {useRouter} from "next/navigation"
|
||||
|
||||
export function Providers({children}: { children: React.ReactNode }) {
|
||||
const router = useRouter();
|
||||
@ -84,7 +84,7 @@ import {Providers} from "./providers";
|
||||
|
||||
export default function RootLayout({children}: { children: React.ReactNode }) {
|
||||
return (
|
||||
<html lang="en" className='dark'>
|
||||
<html lang="en" className="dark">
|
||||
<body>
|
||||
<Providers>
|
||||
{children}
|
||||
@ -99,11 +99,11 @@ export default function RootLayout({children}: { children: React.ReactNode }) {
|
||||
|
||||
#### Add useHref (Optional)
|
||||
|
||||
If you are using the Next.js [basePath](https://nextjs.org/docs/app/api-reference/next-config-js/basePath) setting, you'll need to configure an environment variable to access it.
|
||||
If you are using the Next.js [basePath](https://nextjs.org/docs/app/api-reference/next-config-js/basePath) setting, you'll need to configure an environment variable to access it.
|
||||
|
||||
```js
|
||||
// next.config.js
|
||||
const basePath = '...';
|
||||
const basePath = "...";
|
||||
const nextConfig = {
|
||||
basePath,
|
||||
env: {
|
||||
@ -115,10 +115,10 @@ Then, provide a custom `useHref` function to prepend it to the href for all link
|
||||
|
||||
```tsx {9,12}
|
||||
// app/providers.tsx
|
||||
'use client'
|
||||
"use client"
|
||||
|
||||
import {NextUIProvider} from '@nextui-org/react';
|
||||
import {useRouter} from 'next/navigation'
|
||||
import {NextUIProvider} from "@nextui-org/react";
|
||||
import {useRouter} from "next/navigation"
|
||||
|
||||
export function Providers({children}: { children: React.ReactNode }) {
|
||||
const router = useRouter();
|
||||
@ -136,14 +136,14 @@ export function Providers({children}: { children: React.ReactNode }) {
|
||||
|
||||
### Pages Router
|
||||
|
||||
Go to pages`/_app.js` or `pages/_app.tsx` (create it if it doesn't exist) and add the`useRouter` hook
|
||||
Go to pages`/_app.js` or `pages/_app.tsx` (create it if it doesn't exist) and add the`useRouter` hook
|
||||
from `next/router`, it returns a router object that can be used to perform navigation.
|
||||
|
||||
```tsx {7,10}
|
||||
// pages/_app.tsx
|
||||
import type { AppProps } from 'next/app';
|
||||
import {NextUIProvider} from '@nextui-org/react';
|
||||
import {useRouter} from 'next/router';
|
||||
import type { AppProps } from "next/app";
|
||||
import {NextUIProvider} from "@nextui-org/react";
|
||||
import {useRouter} from "next/router";
|
||||
|
||||
function MyApp({ Component, pageProps }: AppProps) {
|
||||
const router = useRouter();
|
||||
@ -162,9 +162,9 @@ When using the [basePath](https://nextjs.org/docs/app/api-reference/next-config-
|
||||
|
||||
```tsx {8,11}
|
||||
// pages/_app.tsx
|
||||
import type { AppProps } from 'next/app';
|
||||
import {NextUIProvider} from '@nextui-org/react';
|
||||
import {useRouter} from 'next/router';
|
||||
import type { AppProps } from "next/app";
|
||||
import {NextUIProvider} from "@nextui-org/react";
|
||||
import {useRouter} from "next/router";
|
||||
|
||||
function MyApp({ Component, pageProps }: AppProps) {
|
||||
const router = useRouter();
|
||||
@ -182,17 +182,17 @@ export default MyApp;
|
||||
|
||||
## React Router
|
||||
|
||||
The `useNavigate` hook from `react-router-dom` returns a `navigate` function that can be used to perform navigation.
|
||||
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
|
||||
Go to the `App` file commonly called `App.jsx` or `App.tsx`, add the `useNavigate` hook and pass the
|
||||
`navigate` function to the `NextUIProvider`:
|
||||
|
||||
```jsx {6,9}
|
||||
// App.tsx or App.jsx
|
||||
import {BrowserRouter, useNavigate, useHref} from 'react-router-dom';
|
||||
import {NextUIProvider} from '@nextui-org/react';
|
||||
import {BrowserRouter, useNavigate, useHref} from "react-router-dom";
|
||||
import {NextUIProvider} from "@nextui-org/react";
|
||||
|
||||
function App() {
|
||||
const navigate = useNavigate();
|
||||
@ -210,7 +210,7 @@ function App() {
|
||||
|
||||
|
||||
// main.tsx or main.jsx
|
||||
ReactDOM.createRoot(document.getElementById('root')).render(
|
||||
ReactDOM.createRoot(document.getElementById("root")).render(
|
||||
<React.StrictMode>
|
||||
<BrowserRouter>
|
||||
<App />
|
||||
@ -219,22 +219,22 @@ ReactDOM.createRoot(document.getElementById('root')).render(
|
||||
)
|
||||
```
|
||||
|
||||
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>`
|
||||
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](https://remix.run/docs/en/main/file-conventions/root)
|
||||
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](https://remix.run/docs/en/main/file-conventions/root)
|
||||
for more details.
|
||||
|
||||
```jsx {14}
|
||||
// app/root.tsx
|
||||
import {useNavigate, useHref, Outlet} from '@remix-run/react';
|
||||
import {NextUIProvider} from '@nextui-org/react';
|
||||
import {useNavigate, useHref, Outlet} from "@remix-run/react";
|
||||
import {NextUIProvider} from "@nextui-org/react";
|
||||
|
||||
export default function App() {
|
||||
const navigate = useNavigate();
|
||||
@ -257,17 +257,17 @@ export default function App() {
|
||||
|
||||
## TanStack
|
||||
|
||||
To use [TanStack Router](https://tanstack.com/router/latest) with NextUI, render NextUI's RouterProvider inside your root route. Use `router.navigate` in the `navigate` prop, and `router.buildLocation` in the `useHref` prop.
|
||||
To use [TanStack Router](https://tanstack.com/router/latest) with NextUI, render NextUI's RouterProvider inside your root route. Use `router.navigate` in the `navigate` prop, and `router.buildLocation` in the `useHref` prop.
|
||||
|
||||
```tsx {9,10}
|
||||
// app/root.tsx
|
||||
import {NextUIProvider} from '@nextui-org/react';
|
||||
import {NextUIProvider} from "@nextui-org/react";
|
||||
|
||||
function RootRoute() {
|
||||
let router = useRouter();
|
||||
|
||||
return (
|
||||
<NextUIProvider
|
||||
<NextUIProvider
|
||||
navigate={(to, options) => router.navigate({ to, ...options })}
|
||||
useHref={(to) => router.buildLocation({ to }).href}
|
||||
>
|
||||
@ -279,7 +279,7 @@ function RootRoute() {
|
||||
|
||||
## Usage examples
|
||||
|
||||
Now that you have set up the `NextUIProvider` in your app, you can use the `href` prop in the `Tabs`,
|
||||
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](/docs/components/link) component will also use the `navigate` function from the
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user