nuqs icon indicating copy to clipboard operation
nuqs copied to clipboard

Reason for window.location is been used and not router.query

Open TommySorensen opened this issue 3 years ago • 4 comments

Hi all

I was just wondering why this package is getting the query based on location object and not the router.query. Isn't the whole point of router.isReady when the Next code is ready to safely read router.query object?

https://nextjs.org/docs/api-reference/next/router#router-object isReady: boolean Whether the router fields are updated client-side and ready for use. Should only be used inside of useEffect methods and not for conditionally rendering on the server. See related docs for use case with automatically statically optimized pages

TommySorensen avatar Oct 07 '22 15:10 TommySorensen

It had to do with optimisation to avoid infinite re-render loops, not sure if it is still relevant. I didn't know about the isReady attribute, thanks for pointing it out.

Related: https://github.com/47ng/next-usequerystate/issues/282#issuecomment-1029579799

franky47 avatar Oct 07 '22 15:10 franky47

Sames goes for the previous version of this package where you used asPath. I guess you changed that because of exactly this comment?

Using the asPath field may lead to a mismatch between client and server if the page is rendered using server-side rendering or automatic static optimization. Avoid using asPath until the isReady field is true.

TommySorensen avatar Oct 07 '22 15:10 TommySorensen

@franky47 I think this package should rely only on the router and nothing else. I have tried implementing something similar as this package with asPath and window object and you will end up in edge cases you can't solve. I have only bad experience with location object and router combined 🙂

TommySorensen avatar Oct 07 '22 15:10 TommySorensen

@TommySorensen, depending on router for reading query params causes a whole heap of problems. What you say is probably true for navigation.

  1. Problems arise waiting on is Ready. Presumably the initial value of the state should resolve as query param value then default value. This means the created state variables will not have an initial value. A lot of code assumes states will have an initial value.

  2. When calling push or replace on the router a new router is created. So if you want a set state that updates the router and also waits for router.isReady and uses it as a dependency, you end up with an infinite loop.

If you have a working example that avoids these pitfalls, please share.

dopry avatar Dec 13 '22 05:12 dopry