服务器端使用
服务器端类型安全的搜索参数
Loaders
Introduced in version 2.3.0.
要在服务器端解析搜索参数,您可以使用 loader 函数。
您可以使用 createLoader 函数创建一个 loader,通过传递搜索参数描述符对象来实现:
import { parseAsFloat, createLoader } from 'nuqs/server'
// 描述您的搜索参数,并在 useQueryStates / createSerializer 中重用它:
export const coordinatesSearchParams = {
latitude: parseAsFloat.withDefault(0),
longitude: parseAsFloat.withDefault(0)
}
export const loadSearchParams = createLoader(coordinatesSearchParams)在这里,loadSearchParams 是一个解析搜索参数并返回服务器端可消费的状态变量的函数(与 useQueryStates 返回的相同状态类型)。
import { loadSearchParams } from './search-params'
import type { SearchParams } from 'nuqs/server'
type PageProps = {
searchParams: Promise<SearchParams>
}
export default async function Page({ searchParams }: PageProps) {
const { latitude, longitude } = await loadSearchParams(searchParams)
return <Map
lat={latitude}
lng={longitude}
/>
// 专业提示:您不必等待结果。
// 将 Promise 对象传递给用 <Suspense> 包裹的子组件
// 以受益于 PPR / dynamicIO,并在搜索参数可用时立即提供静态外壳,
// 同时流式传输依赖于搜索参数的动态部分。
}import type { GetServerSidePropsContext } from 'next'
export async function getServerSideProps({ query }: GetServerSidePropsContext) {
const { latitude, longitude } = loadSearchParams(query)
// 使用坐标进行一些服务器端计算
return {
props: { ... }
}
}export function loader({ request }: LoaderFunctionArgs) {
const { latitude, longitude } = loadSearchParams(request) // request.url 也可以
// 使用坐标进行一些服务器端计算
return ...
}// 注意:您也可以在客户端(或任何地方)使用它,
// 用于一次性解析非响应式搜索参数:
loadSearchParams('https://example.com?latitude=42&longitude=12')
loadSearchParams(location.search)
loadSearchParams(new URL(...))
loadSearchParams(new URLSearchParams(...))// App router,例如:app/api/location/route.ts
export async function GET(request: Request) {
const { latitude, longitude } = loadSearchParams(request)
// ...
}
// Pages router,例如:pages/api/location.ts
import type { NextApiRequest, NextApiResponse } from 'next'
export default function handler(
request: NextApiRequest,
response: NextApiResponse
) {
const { latitude, longitude } = loadSearchParams(request.query)
}Loader 函数将接受以下输入类型来解析搜索参数:
- 包含完整 URL 的字符串:
https://example.com/?foo=bar - 仅包含搜索参数的字符串:
?foo=bar(类似于location.search) - 一个
URL对象 - 一个
URLSearchParams对象 - 一个
Request对象 - 一个
Record<string, string | string[] | undefined>(例如:{ foo: 'bar' }) - 以上任何类型的
Promise,在这种情况下,它也会返回一个 Promise。
严格模式
Introduced in version 2.5.0.
如果搜索参数包含与关联解析器不兼容的值(例如:?count=banana 用于 parseAsInteger),
默认行为是如果指定了默认值,则返回 默认值,否则返回 null。
您可以开启 严格模式,以便在运行 loader 时对无效值抛出错误:
const loadSearchParams = createLoader({
count: parseAsInteger.withDefault(0)
})
// 默认:将返回 { count: 0 }
loadSearchParams('?count=banana')
// 严格模式:将抛出错误
loadSearchParams('?count=banana', { strict: true })
// [nuqs] 解析查询 `banana` 的键 `count` 时出错Cache
Introduced in version 1.13.0.
如果您希望在深度嵌套的服务器组件中访问 searchParams
(即不在页面组件中),您可以使用 createSearchParamsCache
以类型安全的方式实现。
可以将它视为一个 loader 与一种传播解析值到 RSC 树的方式的组合,就像客户端上的 Context 一样。
import {
createSearchParamsCache,
parseAsInteger,
parseAsString
} from 'nuqs/server'
// 注意:从 'nuqs/server' 导入以避免 "use client" 指令
export const searchParamsCache = createSearchParamsCache({
// 在此处列出您的搜索参数键和关联解析器:
q: parseAsString.withDefault(''),
maxResults: parseAsInteger.withDefault(10)
})import { searchParamsCache } from './searchParams'
import { type SearchParams } from 'nuqs/server'
type PageProps = {
searchParams: Promise<SearchParams> // Next.js 15+:异步 searchParams 属性
}
export default async function Page({ searchParams }: PageProps) {
// ⚠️ 不要忘记在此处调用 `parse`。
// 您可以从返回的对象中访问类型安全的数值:
const { q: query } = await searchParamsCache.parse(searchParams)
return (
<div>
<h1>搜索结果:{query}</h1>
<Results />
</div>
)
}
function Results() {
// 在子服务器组件中访问类型安全的搜索参数:
const maxResults = searchParamsCache.get('maxResults')
return <span>最多显示 {maxResults} 个结果</span>
}Cache 仅在当前页面渲染期间有效
(参见 React 的 cache 函数)。
注意:cache 仅适用于 服务器组件,但您可以将
您的解析器声明与 useQueryStates 共享,以在客户端组件中实现类型安全:
import {
parseAsFloat,
createSearchParamsCache
} from 'nuqs/server'
export const coordinatesParsers = {
lat: parseAsFloat.withDefault(45.18),
lng: parseAsFloat.withDefault(5.72)
}
export const coordinatesCache = createSearchParamsCache(coordinatesParsers)import { coordinatesCache } from './searchParams'
import { Server } from './server'
import { Client } from './client'
export default async function Page({ searchParams }) {
// 注意:您也可以在此处使用严格模式:
await coordinatesCache.parse(searchParams, { strict: true })
return (
<>
<Server />
<Suspense>
<Client />
</Suspense>
</>
)
}import { coordinatesCache } from './searchParams'
export function Server() {
const { lat, lng } = coordinatesCache.all()
// 或者单独访问键:
const lat = coordinatesCache.get('lat')
const lng = coordinatesCache.get('lng')
return (
<span>
纬度:{lat} - 经度:{lng}
</span>
)
}'use client'
import { useQueryStates } from 'nuqs'
import { coordinatesParsers } from './searchParams'
export function Client() {
const [{ lat, lng }, setCoordinates] = useQueryStates(coordinatesParsers)
// ...
}更短的搜索参数键
就像使用 useQueryStates 一样,您可以
定义一个 urlKeys 对象来将解析器定义的变量名映射到
URL 中的更短键。它们将被读取时翻译,并且您的代码库
只能引用对您的领域或业务逻辑有意义的变量名。
export const coordinatesParsers = {
// 在整个代码库中使用人类可读的变量名
latitude: parseAsFloat.withDefault(45.18),
longitude: parseAsFloat.withDefault(5.72)
}
export const coordinatesCache = createSearchParamsCache(coordinatesParsers, {
urlKeys: {
// 将它们重新映射为从 URL 中的更短键读取
latitude: 'lat',
longitude: 'lng'
}
})