Basic usage
Replacing React.useState with useQueryState
Prerequisite
Have you setup your app with the appropriate adapter? Then you are all set!
If you are using React.useState
to manage your local UI state,
you can replace it with useQueryState
to sync it with the URL.
'use client'
import { useQueryState } from 'nuqs'
export function Demo() {
const [name, setName] = useQueryState('name')
return (
<>
<input value={name || ''} onChange={e => setName(e.target.value)} />
<button onClick={() => setName(null)}>Clear</button>
<p>Hello, {name || 'anonymous visitor'}!</p>
</>
)
}
<empty query>
useQueryState
takes one required argument: the key to use in the query string.
Like React.useState
, it returns an array with the value present in the query
string as a string (or null
if none was found), and a state updater function.
Example outputs for our demo example:
URL | name value | Notes |
---|---|---|
/ | null | No name key in URL |
/?name= | '' | Empty string |
/?name=foo | 'foo' | |
/?name=2 | '2' | Always returns a string by default, see Parsers |
Tip
Setting null
as a value will remove the key from the query string.
Default values
When the query string is not present in the URL, the default behaviour is to
return null
as state.
It can make state updating and UI rendering tedious. Take this example of a simple counter stored in the URL:
import { useQueryState, parseAsInteger } from 'nuqs'
export default () => {
const [count, setCount] = useQueryState('count', parseAsInteger)
return (
<>
<pre>count: {count}</pre>
<button onClick={() => setCount(0)}>Reset</button>
{/* handling null values in setCount is annoying: */}
<button onClick={() => setCount(c => (c ?? 0) + 1)}>+</button>
<button onClick={() => setCount(c => (c ?? 0) - 1)}>-</button>
<button onClick={() => setCount(null)}>Clear</button>
</>
)
}
You can provide a default value as the second argument to useQueryState
(or
via the .withDefault
builder method on parsers):
const [search] = useQueryState('search', { defaultValue: '' })
// ^? string
const [count] = useQueryState('count', parseAsInteger)
// ^? number | null -> no default value = nullable
const [count] = useQueryState('count', parseAsInteger.withDefault(0))
// ^? number
It makes it much easier to handle state updates:
const increment = () => setCount(c => c + 1) // c will never be null
const decrement = () => setCount(c => c - 1) // c will never be null
const clearCount = () => setCount(null) // Remove query from the URL
Note
The default value is internal to React, it will not be written to the
URL unless you set it explicitly and use the clearOnDefault: false
option.
Tip
The default value is also returned if the value is invalid for the parser.
Tip
Setting the state to null
when a default value is specified:
- Clears the query from the URL
- Returns the default value as state