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
|
Set this up once in the root of your app, and any NextUI component with the href prop will automatically navigate
|
||||||
using your router.
|
using your router.
|
||||||
|
|
||||||
### NextUIProvider Setup
|
## NextUIProvider Setup
|
||||||
|
|
||||||
The `NextUIProvider` accepts a prop called `navigate`. This should be set to a function received from your
|
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
|
router for performing a client side navigation programmatically. The following example shows the general
|
||||||
@ -43,9 +43,9 @@ function App() {
|
|||||||
|
|
||||||
<Spacer y={2} />
|
<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
|
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.
|
`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.
|
> **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>
|
</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
|
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.
|
from `next/router`, it returns a router object that can be used to perform navigation.
|
||||||
|
|
||||||
|
```tsx {7,10}
|
||||||
```tsx {7}
|
|
||||||
// pages/_app.tsx
|
// pages/_app.tsx
|
||||||
import type { AppProps } from 'next/app';
|
import type { AppProps } from 'next/app';
|
||||||
import {NextUIProvider} from '@nextui-org/react';
|
import {NextUIProvider} from '@nextui-org/react';
|
||||||
@ -122,23 +156,47 @@ function MyApp({ Component, pageProps }: AppProps) {
|
|||||||
export default MyApp;
|
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.
|
||||||
|
|
||||||
|
```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 `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`:
|
`navigate` function to the `NextUIProvider`:
|
||||||
|
|
||||||
```jsx {6,9}
|
```jsx {6,9}
|
||||||
// App.tsx or App.jsx
|
// 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';
|
import {NextUIProvider} from '@nextui-org/react';
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NextUIProvider navigate={navigate}>
|
<NextUIProvider navigate={navigate} useHref={useHref}>
|
||||||
{/* Your app here... */}
|
{/* Your app here... */}
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/" element={<HomePage />} />
|
<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
|
element should also be defined inside `NextUIProvider` so that links inside the rendered routes have access
|
||||||
to the router.
|
to the router.
|
||||||
|
|
||||||
|
## Remix
|
||||||
|
|
||||||
### Remix
|
Remix uses React Router under the hood, so the same `useNavigate` and `useHref` hook described above also works in Remix
|
||||||
|
|
||||||
Remix uses React Router under the hood, so the same `useNavigate` hook described above also works in Remix
|
|
||||||
apps. `NextUIProvider` should be rendered at the `root` of each page that includes NextUI components, or in
|
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)
|
`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.
|
for more details.
|
||||||
|
|
||||||
```jsx {14}
|
```jsx {14}
|
||||||
// app/root.tsx
|
// app/root.tsx
|
||||||
import {useNavigate, Outlet} from '@remix-run/react';
|
import {useNavigate, useHref, Outlet} from '@remix-run/react';
|
||||||
import {NextUIProvider} from '@nextui-org/react';
|
import {NextUIProvider} from '@nextui-org/react';
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
@ -186,7 +243,7 @@ export default function App() {
|
|||||||
{/* ... */}
|
{/* ... */}
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<NextUIProvider navigate={navigate}>
|
<NextUIProvider navigate={navigate} useHref={useHref}>
|
||||||
<Outlet />
|
<Outlet />
|
||||||
</NextUIProvider>
|
</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.
|
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`,
|
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.
|
`Listbox` and `Dropdown` items to navigate between pages.
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import type {ModalProviderProps} from "@react-aria/overlays";
|
import type {ModalProviderProps} from "@react-aria/overlays";
|
||||||
import type {ProviderContextProps} from "./provider-context";
|
import type {ProviderContextProps} from "./provider-context";
|
||||||
|
import type {Href} from "@react-types/shared";
|
||||||
|
|
||||||
import {I18nProvider, I18nProviderProps} from "@react-aria/i18n";
|
import {I18nProvider, I18nProviderProps} from "@react-aria/i18n";
|
||||||
import {RouterProvider} from "@react-aria/utils";
|
import {RouterProvider} from "@react-aria/utils";
|
||||||
@ -31,11 +32,20 @@ export interface NextUIProviderProps
|
|||||||
* Link, Menu, Tabs, Table, etc.
|
* Link, Menu, Tabs, Table, etc.
|
||||||
*/
|
*/
|
||||||
navigate?: (path: string) => void;
|
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> = ({
|
export const NextUIProvider: React.FC<NextUIProviderProps> = ({
|
||||||
children,
|
children,
|
||||||
navigate,
|
navigate,
|
||||||
|
useHref,
|
||||||
disableAnimation = false,
|
disableAnimation = false,
|
||||||
disableRipple = false,
|
disableRipple = false,
|
||||||
skipFramerMotionAnimations = disableAnimation,
|
skipFramerMotionAnimations = disableAnimation,
|
||||||
@ -50,7 +60,11 @@ export const NextUIProvider: React.FC<NextUIProviderProps> = ({
|
|||||||
let contents = children;
|
let contents = children;
|
||||||
|
|
||||||
if (navigate) {
|
if (navigate) {
|
||||||
contents = <RouterProvider navigate={navigate}>{contents}</RouterProvider>;
|
contents = (
|
||||||
|
<RouterProvider navigate={navigate} useHref={useHref}>
|
||||||
|
{contents}
|
||||||
|
</RouterProvider>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const context = useMemo<ProviderContextProps>(() => {
|
const context = useMemo<ProviderContextProps>(() => {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user