|
| 1 | +--- |
| 2 | +title: URL State |
| 3 | +sidebar_order: 85 |
| 4 | +--- |
| 5 | + |
| 6 | +**URL state** is any piece of state that should be reflected in the browser URL (typically as query parameters). If a user reloads, shares a link, navigates with back/forward, or opens the page in another tab, the state should be restored from the URL. Typical examples: |
| 7 | + |
| 8 | +- Search queries and filters (e.g., `?project=11276&statsPeriod=14d`) |
| 9 | +- Pagination and sorting (e.g., `?page=3&sort=price`) |
| 10 | +- UI view controls (selected tab, map zoom, layout mode) |
| 11 | +- Lightweight feature switches and flags |
| 12 | + |
| 13 | +<Alert level="warning"> |
| 14 | + Don’t put sensitive or large data into the URL. Keep it human-readable and bounded. |
| 15 | +</Alert> |
| 16 | + |
| 17 | +## nuqs |
| 18 | + |
| 19 | +Going forward, we will be using [nuqs](https://nuqs.dev/) to manage URL state in React. Nuqs is a type-safe search params state manager for React that exposes a `useState` like API that syncs with the URL. It also gracefully handles un-parseable values, supports defaults and throttles updates to the URL out of the box. Nuqs has built-in parsers & serializers for common state types and is customizable so we can make our own. |
| 20 | + |
| 21 | +## Parsers |
| 22 | + |
| 23 | +Per default, everything is parsed as `string`. It is recommended to use any of the built-in parsers or to write your own over doing type assertions or coercions in the component. Types can be inferred from what the parsers return, and it also handles serialization back to the URL. |
| 24 | + |
| 25 | +```tsx |
| 26 | +// parsed as string per default |
| 27 | +const [cursor, setCursor] = useQueryState('cursor') |
| 28 | + |
| 29 | +// with a predefined parser |
| 30 | +const [page, setPage] = useQueryState('page', parseAsNumber) |
| 31 | + |
| 32 | +// with a custom parser |
| 33 | +const [mailbox, setMailbox] = useQueryState('mailbox', parseAsMailbox); |
| 34 | +``` |
| 35 | + |
| 36 | +### Array Parsing |
| 37 | + |
| 38 | +For `SingleParsers`, `nuqs` only considers the first value of a query param in the URL. That means arrays get represented as one value with a separator. |
| 39 | + |
| 40 | +```jsx |
| 41 | +useQueryState('project', parseAsArrayOf(parseAsInteger)) |
| 42 | +// ?project=1,2,3 |
| 43 | +``` |
| 44 | + |
| 45 | +Since we usually want to have Array values represented as multiple url params, we have to use `parseAsNativeArrayOf`, which is a `MultiParser`: |
| 46 | + |
| 47 | +```jsx |
| 48 | +useQueryState('foo', parseAsNativeArrayOf(parseAsInteger)) |
| 49 | +// ?project=1&project=2&project=3 |
| 50 | +``` |
| 51 | + |
| 52 | +## Default Options |
| 53 | + |
| 54 | +Per default, `nuqs` will **replace** the current history entry **without scrolling** to the top of the page. This can be customized on the usage sites: |
| 55 | + |
| 56 | +```jsx |
| 57 | +const [state, setState] = useQueryState( |
| 58 | + 'foo', |
| 59 | + { |
| 60 | + ...parseAsString, |
| 61 | + history: 'push', |
| 62 | + scroll: true, |
| 63 | + } |
| 64 | +) |
| 65 | +``` |
| 66 | + |
| 67 | +Options can also be provided as the second argument to the state setter: |
| 68 | + |
| 69 | +```jsx |
| 70 | +setState('bar', { history: 'push', scroll: true }) |
| 71 | +``` |
0 commit comments