Type-safe search param handling for Next.js using zod.
useSearchParams()
Type-safe search param handling for Next.js using zod.
npm install @jokullsolberg/next-use-search-params
function Signup() {
const [{ foo, bar, date }, setSearchParam] = useSearchParams({
foo: z.string().default(''),
bar: z.coerce.number().default(1),
date: z.coerce.date().default(new Date()),
screen: z.enum(['login', 'signup']).default('login'),
});
return (
<div
style={{
display: 'flex',
flexDirection: 'column',
gap: '10px',
alignItems: 'start',
}}
>
<h2>Signup</h2>
<input
value={foo}
onChange={(event) => setSearchParam('foo', event.target.value)}
/>
<input
type="number"
value={String(bar)}
onChange={(event) => setSearchParam('bar', event.target.valueAsNumber)}
/>
<input
type="date"
value={date.toISOString().split('T')[0]}
onChange={(event) =>
setSearchParam('date', event.target.valueAsDate ?? new Date())
}
/>
<p>{date.toISOString()}</p>
<button onClick={() => setSearchParam('screen', 'login')}>Login</button>
</div>
);
}
export default function Page() {
const [{ screen }, setSearchParam] = useSearchParams({
screen: z.enum(['login', 'signup']).default('login'),
});
return screen === 'login' ? (
<div>
Login{' '}
<button onClick={() => setSearchParam('screen', 'signup')}>Signup</button>
</div>
) : (
<Signup />
);
}
These components can affect the state by simply routing with Link
or router.push
— instead of
prop drilling onSuccess
handlers into each component to orchestrate transitions.
Default values are required. Let me know if this is annoying.
Keeping state in search params is user friendly and has DX benefits
Context
.onSuccess
handlers.preprocess
them? No. Use thez.coerce
stuff instead. Internally we call JSON.stringify
or Date.toISOString()
toThis does not work inside /app
client components since router is imported from next/navigation
now.
SSR will reach for the default values.