适配器
在您选择的 React 框架中使用 nuqs
从 2 版开始,您现在可以在以下 React 框架中使用 nuqs,通过用 NuqsAdapter 上下文提供者包装它:
- Next.js(应用路由器)
- Next.js(页面路由器)
- React SPA(例如:使用 Vite)
- Remix
- React Router v6
- React Router v7
TanStack Router
Next.js
应用路由器
在您的根布局文件中,用 NuqsAdapter 组件包装您的 {children}:
import { NuqsAdapter } from 'nuqs/adapters/next/app'
import { type ReactNode } from 'react'
export default function RootLayout({
children
}: {
children: ReactNode
}) {
return (
<html>
<body>
<NuqsAdapter>{children}</NuqsAdapter>
</body>
</html>
)
}页面路由器
在您的 _app.tsx 文件中,用 NuqsAdapter 组件包装 <Component> 页面出口:
import type { AppProps } from 'next/app'
import { NuqsAdapter } from 'nuqs/adapters/next/pages'
export default function MyApp({ Component, pageProps }: AppProps) {
return (
<NuqsAdapter>
<Component {...pageProps} />
</NuqsAdapter>
)
}统一(路由器无关)
如果您的 Next.js 应用同时使用应用路由器和页面路由器,并且适配器需要挂载在任一路由器上,您可以导入统一适配器,但代价是捆绑包大小略微增大(~100B)。
import { NuqsAdapter } from 'nuqs/adapters/next'适配器的主要原因是向其他 React 框架开放 nuqs:
React SPA
示例,使用 Vite:
import { NuqsAdapter } from 'nuqs/adapters/react'
createRoot(document.getElementById('root')!).render(
<NuqsAdapter>
<App />
</NuqsAdapter>
)注意
由于此配置中没有已知的服务器,shallow: false 选项将无效。
有关一些选项,请参阅以下内容:
在 shallow: false 上进行完整页面导航
您可以指定一个标志,当更新配置了 shallow: false 的查询状态时执行完整页面导航,以通知 Web 服务器 URL 状态已更改,如果服务器需要它来服务器端渲染应用程序的其他部分而非静态 React 捆绑包:
createRoot(document.getElementById('root')!).render(
<NuqsAdapter fullPageNavigationOnShallowFalseUpdates>
<App />
</NuqsAdapter>
)这对于非 JavaScript 编写的服务器可能有用,例如 Django(Python)、Rails(Ruby)、Laravel(PHP)、Phoenix(Elixir)等…
Remix
import { NuqsAdapter } from 'nuqs/adapters/remix'
// ...
export default function App() {
return (
<NuqsAdapter>
<Outlet />
</NuqsAdapter>
)
}React Router v6
import { NuqsAdapter } from 'nuqs/adapters/react-router/v6'
import { createBrowserRouter, RouterProvider } from 'react-router-dom'
import App from './App'
const router = createBrowserRouter([
{
path: '/',
element: <App />
}
])
export function ReactRouter() {
return (
<NuqsAdapter>
<RouterProvider router={router} />
</NuqsAdapter>
)
}仅支持 BrowserRouter。未来可能支持 HashRouter(参见问题 #810),但不支持 MemoryRouter。
React Router v7
import { NuqsAdapter } from 'nuqs/adapters/react-router/v7'
import { Outlet } from 'react-router'
// ...
export default function App() {
return (
<NuqsAdapter>
<Outlet />
</NuqsAdapter>
)
}弃用通知
通用导入 nuqs/adapters/react-router(指向 v6)已被弃用,并将在 nuqs@3.0.0 中移除。
请将您的导入固定到特定版本,例如:nuqs/adapters/react-router/v6 或 nuqs/adapters/react-router/v7。
主要区别在于 React Router 钩子导入的位置:v6 来自 react-router-dom,v7 来自 react-router。
TanStack Router
import { NuqsAdapter } from 'nuqs/adapters/tanstack-router'
import { Outlet, createRootRoute } from '@tanstack/react-router'
export const Route = createRootRoute({
component: () => (
<>
<NuqsAdapter>
<Outlet />
</NuqsAdapter>
</>
),
})TanStack Router 支持是实验性的,尚未涵盖 TanStack Start。
通过 validateSearch 进行类型安全的路由
TanStack Router 自带内置的类型安全搜索参数支持,其 API 很可能应在您的应用程序代码中使用以获得最佳 DX。
尽管如此,有时您可能需要导入使用 nuqs 的组件(来自 NPM 或共享库),并受益于 TanStack Router 的类型安全路由。
您可以通过 标准模式 支持来实现:
import { createFileRoute, Link } from '@tanstack/react-router'
import {
createStandardSchemaV1,
parseAsIndex,
parseAsString,
useQueryStates
} from 'nuqs'
const searchParams = {
searchQuery: parseAsString.withDefault(''),
pageIndex: parseAsIndex.withDefault(0),
}
export const Route = createFileRoute('/search')({
component: RouteComponent,
validateSearch: createStandardSchemaV1(searchParams, {
partialOutput: true
})
})
function RouteComponent() {
// 像往常一样消费 nuqs 状态:
const [{ searchQuery, pageIndex }] = useQueryStates(searchParams)
// 但现在 TanStack Router 也了解它:
return (
<Link
to="/search"
search={{
searchQuery: 'foo',
// 注意:我们没有指定 pageIndex
}}
/>
)
}请注意,partialOutput 标志允许为给定路由指定搜索参数的子集。它也不会自动在 URL 中反映这些搜索,更多遵循 nuqs 的行为。
注意事项
由于 TanStack Router 和 nuqs 在处理序列化和反序列化方面的差异(TanStack Router 中为全局,nuqs 中为每个键),仅支持 简单 状态类型以进行类型安全的链接。这些包括所有基于字符串的解析器(字符串、枚举、字面量)、基于数字的(整数、浮点数、数字字面量)、布尔值和 JSON。
提供简写键名的 urlKeys 功能由于类似原因也不支持。
测试
NuqsTestingAdapter 的文档位于 测试页面。