# NextJS: Add state to URL query params

- Published: 2021-05-20
- URL: https://notes.webutvikling.org/nextjs-store-state-in-url-query
- Tags: nextjs

I lovehate putting state in the url. You can create complex wizards or flows with a shareable url-state
which you can store or send to a team. All without even having a backend or a login.

### TLDR

`yarn add next-usequerystate`

#### Simple string

[Gist](https://gist.github.com/1881e789120830ee8a805f3dd2959a25)

#### JSON

[Gist](https://gist.github.com/1881e789120830ee8a805f3dd2959a25)

### The long story

Check out how the URL changes based on your answers at [ihasabucket.it](https://ihasabucket.it/).

There's many reasons for putting the state in the URL:

- You can share the results to your team, or store them for later.
- When helping someone out you can link them a prefilled form, saying "I think this is right for you".
- There's no backend to implement.
- Loading data from the browser is faster than from an API.
- Error logging to a third party service like Sentry, includes the state in which the error occurred.

There are a few things to get correctly and watch out for, though:

- You can quickly end up in a rerender loop as you write to and read from the history api.
- Avoid poor performance by updating the URL query async from the state changes.
- You want to _consider_ using [replaceState over pushState](https://developer.mozilla.org/en-US/docs/Web/API/History_API) – but not always.
- Make your data URL safe before updating history.
- If you store JSON, you may want to base64 encode it or compress it.
- If you store JSON, your application should handle old (now invalid) data structures.
- With NextJS, do not call `router.push` twice in one function. The latter change will override the first.
- With NextJS (SSR/SSG), [do not rely on `router.query` to provide a variables initial value](https://github.com/vercel/next.js/discussions/11484). Instead, update the variable with `useMemo` (due to how rehydration).

Below are my attempts at getting around these things. For the future, I'd recommend using
[next-usequerystate](https://www.npmjs.com/package/next-usequerystate) to handle the complexity.

- (Simple) [Gist for storing string variables in URL](https://gist.github.com/tomfa/9bf850bbaeb421c77d2b1bd2a158ae10)
- (Harder) [Gist for storing JSON state in URL](https://gist.github.com/tomfa/fcb8838881080788e139cb2fc2364fcd)

_There is one gotcha: You can not call two different `setQueryState` functions in the same render.
The latter will override changes to the query params done by the former._
