Keep Search Params on NextJS Link Navigation #766
-
I try to keep the state url after navigating with the NextJS Link Component. I am using nextjs 15 with app router. I use this simple example for testing:
import { MapControls, MapView } from '@/components/test';
import Link from 'next/link';
export default function Home() {
return (
<div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]">
<MapView />
<MapControls />
<div>
<Link href={'/'}>Home</Link>
<Link href={'/next'}>Next</Link>
</div>
</div>
);
}
'use client';
import { useCoordinates } from '@/hooks/use-url';
function MapView() {
const [{ lat, lng }] = useCoordinates(); // Read-only
return (
<div>
Latitude: {lat}
Longitude: {lng}
</div>
);
}
function MapControls() {
const [{ lat, lng }, setCoordinates] = useCoordinates();
return (
<div>
<input
type="number"
value={lat}
onChange={(e) => setCoordinates({ lat: e.target.valueAsNumber })}
/>
<input
type="number"
value={lng}
onChange={(e) => setCoordinates({ lng: e.target.valueAsNumber })}
/>
</div>
);
}
export { MapView, MapControls }; When I use the Link Components to navigate between home and test I lose the url state. How to persist the search params? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 4 replies
-
You can leverage the serializer helper along with Next's stock useSearchParams to generate links that persist the current search params: import { MapControls, MapView } from '@/components/test';
import { createSerializer, type inferParserType } from 'nuqs/server'
import Link from 'next/link';
import { useSearchParams } from 'next/navigation'
// Import the same parsers as you used in useCoordinates
const serialize = createSerializer(coordinatesParsers)
function usePersistedSearchParamsLink(
base: string,
values: Partial<inferParserType<typeof coordinateParsers>> = {}
) {
const searchParams = useSearchParams()
return base + serialize(searchParams, values)
}
export default function Home() {
return (
<div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]">
<MapView />
<MapControls />
<div>
<Link href={usePersistedSearchParamsLink('/')}>Home</Link>
<Link href={usePersistedSearchParamsLink('/next')}>Next</Link>
<Link href={usePersistedSearchParamsLink('/specific', { lat: 1.23, lng: 4.56 })}>Next</Link>
</div>
</div>
);
} I had prototyped a build-in way to do this with nuqs, extending the serializer to allow declaring which search params to persist, and allowing overriding their value when generating a link, a bit like in TanStack Router. Maybe it could be worth investigating this a bit more. |
Beta Was this translation helpful? Give feedback.
-
Now I have this file for setting up the hook and function to get the search urls to pass them with Link Component: 'use client'
import { useSearchParams } from 'next/navigation'
import { useQueryStates, parseAsString } from 'nuqs'
import { createSerializer, type inferParserType } from 'nuqs/server'
const queryParams = {
search: parseAsString.withDefault(''),
category: parseAsString.withDefault(''),
subcategory: parseAsString,
}
const useQueryParams = () => {
return useQueryStates(queryParams)
}
const serialize = createSerializer(queryParams)
function usePersistedSearchParamsLink(
base: string,
values: Partial<inferParserType<typeof queryParams>> = {}
) {
const searchParams = useSearchParams()
return base + serialize(searchParams, values)
}
export { useQueryParams, usePersistedSearchParamsLink } When Navigating with the Link component everything work fine. When I navigate without the 'use client'
import { Input } from './ui/input'
import { useQueryParams } from '@/hooks/use-query-params'
export default function SearchbarText() {
const [{ search }, setQueryParams] = useQueryParams()
return (
<Input
type="text"
placeholder="Was suchts du?"
className="rounded-l-none"
value={search}
onChange={(e) => setQueryParams({ search: e.target.value })}
/>
)
} Initially the value gets reset to an empty string. When I type in a new string the value jumps to the old string before navigation. It seems like the value gets hydrated just after editing it. I have this component in Root Layout of my nextjs project. Can that be the problem? |
Beta Was this translation helpful? Give feedback.
You can leverage the serializer helper along with Next's stock useSearchParams to generate links that persist the current search params: