-
-
Notifications
You must be signed in to change notification settings - Fork 135
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
update
a.k.a setter function is not stable in v2
#852
Comments
Thanks for the detailed report! I fixed this in #841, could you give |
Awesome! Tested this version both in demo examples and in our project which uses We'll use Thanks for your quick response and your work in general! |
Good, let me know if you hit any snags with the beta, I'm planning on shipping 2.3.1 tomorrow. |
|
Context
What's your version of
nuqs
?What framework are you using?
✅ Next.js (app router)
Which version of your framework are you using?
Description
nuqs
update
function a.k.a setter inuseQueryState(s)
is no longer stable (by reference) in v2 in contrast to v1v1 perfectly aligns with
react
's ownuseState
thesetState
of which is guaranteed to be stablev2 breaks this behavior
The following
useEffect
will run indefinitely in a loop in v2, but not in v1:Reproduction
I set up a simple next.js starter repo with nuqs and hosted it on Vercel:
V2: GitHub v2 | Vercel v2
v1: GitHub v1 | Vercel v1
Running setUsername
printed in an infinite loop to console inv2
Running setUsername
printed once only inv1
Demo:
CleanShot.2025-01-08.at.21.23.52.mp4
The point of interest is NUQS component.
Research
The
update
function in v1 had the following dependency array, which works just fine:nuqs/packages/nuqs/src/useQueryState.ts
Line 313 in 79f80da
The v2 has introduced
adapter
to the dependency array:nuqs/packages/nuqs/src/useQueryState.ts
Line 297 in 10e526d
adapter
is a context value which is a composite object:nuqs/packages/nuqs/src/adapters/next/impl.app.ts
Lines 42 to 47 in 10e526d
In this context
updateUrl
is stable locally thanks to an empty dependency array ([]
) ofuseCallback
nuqs/packages/nuqs/src/adapters/next/impl.app.ts
Lines 40 to 41 in 10e526d
However the object that is
return
'ed is dynamic (recreated on every render)Simplified React Example
Current context provider for nuqs adapters can be simplified to the following snippet, where
compositeObjectValue
, used by context consumers will not be stable:compositeObjectValue
here representsadapter
:nuqs/packages/nuqs/src/useQueryState.ts
Line 297 in 10e526d
Possible solutions
update
function to rely on stable object values instead of a dynamic object itself (if possible):update
function in dependency arrays.It also has to be stated that
useQueryState
'supdate
does not align withuseState
'ssetState
in terms of stabilityExtra thoughts
From our side (as consumers of this library) a solution is to remove
update
functions ofuseQueryState(s)
from all dependency arrays. It works just fine and having it specified is, probably, redundant in the first place.However, placing a setter function in a dependency array is not a violation in any case and is perfectly fine according to React.
Eslit's
react-hooks/exhaustive-deps
highlights the need to add anupdate
function to the dependency array, so that is what many devs might just do.P.S. @franky47 Thanks for your work on this amazing library which is really helpful and is a pleasure to use! Looking forward to many years of collaboration!
The text was updated successfully, but these errors were encountered: