nuqs: Server client html mismatch occurs on first render
Warnings like Warning: Expected server HTML to contain a matching <button> in <div>.
occurs because html was rendered with no url params on server side, but rendered with url params in client side.
I think Next.js handles this problem by setting router.query to an empty object on the first render, and sets client url params on the next render. But because useUrlState uses window.location.search and not router, this warning occurs.
This can be avoided by using code like this:
const [queryState, setQueryState] = useQueryState(...);
const [state, setState] = useState();
useEffect(() => setState(queryState), [queryState]);
But it would be better if this boilerplate could be avoided in some way.
About this issue
- Original URL
- State: open
- Created 2 years ago
- Reactions: 13
- Comments: 23 (4 by maintainers)
Got hit by this as well.
FWIW - we are using this wrapper hook as a workaround. It’s based on @doxylee’s comment above. Haven’t really battle tested it that much, but seems to do the job for the time being.
☮️
You’re absolutely right - this is exactly what was happening
I had this happen before, in my case I had bad useEffect which continuously tried to update the state, which lead to constant navigation to new query, which led to being unable to navigate away.
Easiest way to check is to enable “Highlight updates when components render.” in react devtools extension: and see if the page is continiusly flashing.
Isn’t this a major issue? This means this boilerplate has to be used by everyone, or am I missing something?
I think the correct solution would be to always return the default value on both server and client-side on the initial render. Reading from
window.location
should be done in an effect. See this article for an in-depth explanation of why this is important https://joshwcomeau.com/react/the-perils-of-rehydration/There are some other drawbacks on the above code, like
state
being one frame(?) late compared toqueryState
. Maybe this would be better?