-
-
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
Dynamic keys in useQueryStates #799
Comments
I see, what you want is a dynamic set of keys in the object passed to I'll see if it's doable without causing a ton of re-renders in normal use-cases (due to that object often being declared inline and so being recreated on each render). |
@franky47 Thank you so much for looking into it! |
This library is excellent, but it requires |
@taymoor89 would you be able to share more about your use-case? The idea for dynamic keys would be that:
The reason being that it would be non type-safe to do point n°2: dynamic states like this would not be representable statically. Also, for performance reasons, detecting changes in the parsers (which are not referentially stable across renders when defined inline, which is usually the way they are specified, and the only way to do this dynamically) would cause a lot of undesired re-renders. That would mean that all parsers under dynamic keys would have to be the same. |
Joining the discussion here. I enabled nuqs debug mode and identified the issue. Although we maintain a state for the ‘parsers’ and update useQueryStates accordingly, the subscription to the parameters occurs at a later stage. This delay causes the subsequent setState calls to be missed by nuqs, resulting in the state being treated as external. Here’s a simplified onChange function example that replicates the issue: const { parsers, setParsers } = useState(initialParsers);
const [state, setState] = useQueryStates(parsers);
const onChange = (newState: Array<{id: string, value: string}>) => {
const nextParsers = Object.fromEntries(newState.map(i => [i.id, parseAsString]))
// Update parsers first
setParsers(() => nextParsers);
// Then update state
setState(() => newState); //Doesn't do anything (for new fields, works on a second render of a field)
}; In this case, calling setParsers before setState doesn’t work as expected because nuqs doesn’t re-subscribe to the updated parsers. Attempts to use setTimeout or useTransition doesn't help, as these do not guarantee synchronization of subscriptions with nuqs. |
Could y'all try @yarinsa, regarding setting the parsers and state at the same time: you will need to wait for the |
@franky47 Thanks for looking into it! Unfortunately I'm still seeing the same behavior using |
We were able get around this issue by making sure that the component where the queryParams are defined is not rendered until the underlying data is loaded. This won't help if you need the queryParams to change after the initial params are fetched, but it does work for our scenario. |
I found the issue about why reading the values didn't sync with key updates (it was a classic cache invalidation issue). Could you please try this preview build and let me know how it goes? @erinleigh90 it seems to pass your repro.
Note that the values will still be picked up on the next render after the keys have been updated. |
Context
What's your version of
nuqs
?What framework are you using?
Which version of your framework are you using?
Description
We need expected queryParams to be populated dynamically from retrieved data. However, when the queryStates are populated after the relevant data is fetched, pre-existing queryParams in the url are not applied to the new queryStates. I don't know if this would technically count as a bug or a feature request, but either way I need a way to capture the initial state of queryParams once our filters have been populated.
Originally posted here: #531
Reproduction
Minimal Reproduction:
https://github.com/erinleigh90/nuqs-dynamic-query-states
Steps to reproduce the behavior:
The text was updated successfully, but these errors were encountered: