skip to content
Notes && Anecdotes
NextJS logoNextJS logo

NextJS: Add state to URL query params


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.


yarn add next-usequerystate

Simple string


The long story

Check out how the URL changes based on your answers at

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 occured.

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 – 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. 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 to handle the complexity.

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.