@@ -285,45 +285,6 @@ export default () => {
285285}
286286```
287287
288- ### Using parsers in Server Components
289-
290- > Note: see the [ Accessing searchParams in server components] ( #accessing-searchparams-in-server-components )
291- > section for a more user-friendly way to achieve type-safety.
292-
293- If you wish to parse the searchParams in server components, you'll need to
294- import the parsers from ` nuqs/server ` , which doesn't include
295- the ` "use client" ` directive.
296-
297- You can then use the ` parseServerSide ` method:
298-
299- ``` tsx
300- import { parseAsInteger } from ' nuqs/server'
301-
302- type PageProps = {
303- searchParams: {
304- counter? : string | string []
305- }
306- }
307-
308- const counterParser = parseAsInteger .withDefault (1 )
309-
310- export default function ServerPage({ searchParams }: PageProps ) {
311- const counter = counterParser .parseServerSide (searchParams .counter )
312- console .log (' Server side counter: %d' , counter )
313- return (
314- ...
315- )
316- }
317- ```
318-
319- See the [ server-side parsing demo] ( < ./packages/docs/src/app/playground/(demos)/pagination > )
320- for a live example showing how to reuse parser configurations between
321- client and server code.
322-
323- > Note: parsers ** don't validate** your data. If you expect positive integers
324- > or JSON-encoded objects of a particular shape, you'll need to feed the result
325- > of the parser to a schema validation library, like [ Zod] ( https://zod.dev ) .
326-
327288## Default value
328289
329290When the query string is not present in the URL, the default behaviour is to
@@ -642,6 +603,10 @@ const { q, page } = loadSearchParams('?q=hello&page=2')
642603
643604It accepts various types of inputs (strings, URL, URLSearchParams, Request, Promises, etc.). [ Read more] ( https://nuqs.47ng.com/docs/server-side#loaders )
644605
606+ See the [ server-side parsing demo] ( < ./packages/docs/src/app/playground/(demos)/pagination > )
607+ for a live example showing how to reuse parser configurations between
608+ client and server code.
609+
645610## Accessing searchParams in Server Components
646611
647612If you wish to access the searchParams in a deeply nested Server Component
@@ -930,25 +895,62 @@ export const metadata: Metadata = {
930895If however the query string is defining what content the page is displaying
931896(eg: YouTube's watch URLs, like ` https://www.youtube.com/watch?v=dQw4w9WgXcQ ` ),
932897your canonical URL should contain relevant query strings, and you can still
933- use ` useQueryState ` to read it:
898+ use your parsers to read it, and to serialize the canonical URL :
934899
935900``` ts
936901// page.tsx
937902import type { Metadata , ResolvingMetadata } from ' next'
938- import { useQueryState } from ' nuqs'
939- import { parseAsString } from ' nuqs/server'
903+ import { notFound } from ' next/navigation'
904+ import {
905+ createParser ,
906+ parseAsString ,
907+ createLoader ,
908+ createSerializer ,
909+ type SearchParams ,
910+ type UrlKeys
911+ } from ' nuqs/server'
912+
913+ const youTubeVideoIdRegex = / ^ [^ "&?\/ \s ] {11} $ / i
914+ const youTubeSearchParams = {
915+ videoId: createParser ({
916+ parse(query ) {
917+ if (! youTubeVideoIdRegex .test (query )) {
918+ return null
919+ }
920+ return query
921+ },
922+ serialize(videoId ) {
923+ return videoId
924+ }
925+ })
926+ }
927+ const youTubeUrlKeys: UrlKeys <typeof youTubeSearchParams > = {
928+ videoId: ' v'
929+ }
930+ const loadYouTubeSearchParams = createLoader (youTubeSearchParams , {
931+ urlKeys: youTubeUrlKeys
932+ })
933+ const serializeYouTubeSearchParams = createSerializer (youTubeSearchParams , {
934+ urlKeys: youTubeUrlKeys
935+ })
936+
937+ // --
940938
941939type Props = {
942- searchParams: { [ key : string ] : string | string [] | undefined }
940+ searchParams: Promise < SearchParams >
943941}
944942
945943export async function generateMetadata({
946944 searchParams
947945}: Props ): Promise <Metadata > {
948- const videoId = parseAsString .parseServerSide (searchParams .v )
946+ const { videoId } = await loadYouTubeSearchParams (searchParams )
947+ if (! videoId ) {
948+ notFound ()
949+ }
949950 return {
950951 alternates: {
951- canonical: ` /watch?v=${videoId } `
952+ canonical: serializeYouTubeSearchParams (' /watch' , { videoId })
953+ // /watch?v=dQw4w9WgXcQ
952954 }
953955 }
954956}
0 commit comments