mirror of
https://github.com/nextui-org/nextui.git
synced 2025-12-08 19:26:11 +00:00
fix(system): missing useHref logic (#2943)
* chore(deps): update pnpm-lock.yaml * fix(system): missing useHref logic * chore(docs): restructure heading * feat(docs): add useHref content to routing page * fix(hooks): revise useAriaLink onClick logic * chore(deps): bump @react-types/shared * chore(deps): bump @react-types/shared * fix(hooks): add missing parameters * fix(pagination): add missing parameters * feat(changeset): add missing router.open parameters due to rounter change * fix(docs): onSelectionChange type * refactor(changeset): revise changeset message * chore(deps): lock deps * chore(hooks): bump @react-types/shared to 3.23.0 * chore(changeset): remove this changeset since it is already in canary
This commit is contained in:
parent
3ed05abe10
commit
4ac7674d1e
5
.changeset/curvy-eels-tap.md
Normal file
5
.changeset/curvy-eels-tap.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"@nextui-org/system": patch
|
||||
---
|
||||
|
||||
Fix missing `useHref` logic (#2934)
|
||||
@ -17,7 +17,7 @@ component configures all NextUI components within it to navigate using the clien
|
||||
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
|
||||
## 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
|
||||
@ -43,9 +43,9 @@ function App() {
|
||||
|
||||
<Spacer y={2} />
|
||||
|
||||
### Next.js
|
||||
## Next.js
|
||||
|
||||
#### App Router
|
||||
### 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.
|
||||
@ -95,15 +95,49 @@ export default function RootLayout({children}: { children: React.ReactNode }) {
|
||||
|
||||
> **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](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 nextConfig = {
|
||||
basePath,
|
||||
env: {
|
||||
BASE_PATH: basePath
|
||||
}
|
||||
};
|
||||
```
|
||||
Then, provide a custom `useHref` function to prepend it to the href for all links.
|
||||
|
||||
```tsx {9,12}
|
||||
// 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>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
</Steps>
|
||||
|
||||
#### Pages Router
|
||||
### Pages Router
|
||||
|
||||
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}
|
||||
```tsx {7,10}
|
||||
// pages/_app.tsx
|
||||
import type { AppProps } from 'next/app';
|
||||
import {NextUIProvider} from '@nextui-org/react';
|
||||
@ -122,23 +156,47 @@ function MyApp({ Component, pageProps }: AppProps) {
|
||||
export default MyApp;
|
||||
```
|
||||
|
||||
### React Router
|
||||
When using the [basePath](https://nextjs.org/docs/app/api-reference/next-config-js/basePath) configuration option, provide a `useHref` option to the router passed to Provider to prepend it to links automatically.
|
||||
|
||||
The `useNavigate` hook from `react-router-dom` returns a `navigate` function that can be used to perform navigation.
|
||||
```tsx {8,11}
|
||||
// pages/_app.tsx
|
||||
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();
|
||||
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`:
|
||||
|
||||
```jsx {6,9}
|
||||
// App.tsx or App.jsx
|
||||
import {BrowserRouter, useNavigate} from 'react-router-dom';
|
||||
import {BrowserRouter, useNavigate, useHref} from 'react-router-dom';
|
||||
import {NextUIProvider} from '@nextui-org/react';
|
||||
|
||||
function App() {
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<NextUIProvider navigate={navigate}>
|
||||
<NextUIProvider navigate={navigate} useHref={useHref}>
|
||||
{/* Your app here... */}
|
||||
<Routes>
|
||||
<Route path="/" element={<HomePage />} />
|
||||
@ -164,17 +222,16 @@ component (e.g. `BrowserRouter`) so that it has access to React Router's interna
|
||||
element should also be defined inside `NextUIProvider` so that links inside the rendered routes have access
|
||||
to the router.
|
||||
|
||||
## Remix
|
||||
|
||||
### Remix
|
||||
|
||||
Remix uses React Router under the hood, so the same `useNavigate` hook described above also works in 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)
|
||||
for more details.
|
||||
|
||||
```jsx {14}
|
||||
// app/root.tsx
|
||||
import {useNavigate, Outlet} from '@remix-run/react';
|
||||
import {useNavigate, useHref, Outlet} from '@remix-run/react';
|
||||
import {NextUIProvider} from '@nextui-org/react';
|
||||
|
||||
export default function App() {
|
||||
@ -186,7 +243,7 @@ export default function App() {
|
||||
{/* ... */}
|
||||
</head>
|
||||
<body>
|
||||
<NextUIProvider navigate={navigate}>
|
||||
<NextUIProvider navigate={navigate} useHref={useHref}>
|
||||
<Outlet />
|
||||
</NextUIProvider>
|
||||
{/* ... */}
|
||||
@ -196,8 +253,7 @@ export default function App() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### TanStack
|
||||
## 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.
|
||||
|
||||
@ -219,8 +275,7 @@ function RootRoute() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Usage examples
|
||||
## 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.
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import type {ModalProviderProps} from "@react-aria/overlays";
|
||||
import type {ProviderContextProps} from "./provider-context";
|
||||
import type {Href} from "@react-types/shared";
|
||||
|
||||
import {I18nProvider, I18nProviderProps} from "@react-aria/i18n";
|
||||
import {RouterProvider} from "@react-aria/utils";
|
||||
@ -31,11 +32,20 @@ export interface NextUIProviderProps
|
||||
* Link, Menu, Tabs, Table, etc.
|
||||
*/
|
||||
navigate?: (path: string) => void;
|
||||
/**
|
||||
* Convert an `href` provided to a link component to a native `href`
|
||||
* For example, a router might accept hrefs relative to a base path,
|
||||
* or offer additional custom ways of specifying link destinations.
|
||||
* The original href specified on the link is passed to the navigate function of the RouterProvider,
|
||||
* and useHref is used to generate the full native href to put on the actual DOM element.
|
||||
*/
|
||||
useHref?: (href: Href) => string;
|
||||
}
|
||||
|
||||
export const NextUIProvider: React.FC<NextUIProviderProps> = ({
|
||||
children,
|
||||
navigate,
|
||||
useHref,
|
||||
disableAnimation = false,
|
||||
disableRipple = false,
|
||||
skipFramerMotionAnimations = disableAnimation,
|
||||
@ -50,7 +60,11 @@ export const NextUIProvider: React.FC<NextUIProviderProps> = ({
|
||||
let contents = children;
|
||||
|
||||
if (navigate) {
|
||||
contents = <RouterProvider navigate={navigate}>{contents}</RouterProvider>;
|
||||
contents = (
|
||||
<RouterProvider navigate={navigate} useHref={useHref}>
|
||||
{contents}
|
||||
</RouterProvider>
|
||||
);
|
||||
}
|
||||
|
||||
const context = useMemo<ProviderContextProps>(() => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user