Skip to content
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

Array of string with empty query string and default [] is causing Uncaught Error: Maximum update depth exceeded. #948

Closed
shrestha12344 opened this issue Mar 23, 2025 · 8 comments
Labels
bug Something isn't working

Comments

@shrestha12344
Copy link

shrestha12344 commented Mar 23, 2025

Context

What's your version of nuqs?

"nuqs": "^2.4.1",

What framework are you using?

  • ✅Next.js (app router)

Which version of your framework are you using?

"next": "^14.1.0",
"react": "^18",

Description

Array of string with empty query string and default [] is causing Uncaught Error: Maximum update depth exceeded. I am using the state in useCallback dependency. It is working when I remove withDefault([]) but have to add || [] wherever I use the state as its value is null. It is also working when I append '?types=' to URL.

Reproduction

  const [types, setTypes] = useQueryState(
    "types",
    parseAsArrayOf(parseAsString).withDefault([])
  );

This will throw error with empty query in URL when we add that state in useCallback dependency.

@shrestha12344 shrestha12344 added the bug Something isn't working label Mar 23, 2025
@franky47
Copy link
Member

The minimum version of Next.js supported is 14.2.0, early versions of Next.js 14 had issues with routing, prefetching etc (see #423 for reference).

Would you be able to update to 14.2.0 (or better, 14.2.26 which solves the CVE-2025-29927 middleware vulnerability), and see if you still encounter the issue?

@franky47 franky47 added the cannot-reproduce Either no reproduction provided, or cannot reproduce with a minimal setup label Mar 26, 2025
@adriandmitroca
Copy link

I'm experiencing the same thing on Vite-based project with React Router v7, it doesn't seem to be Next related.

@franky47
Copy link
Member

Ah I see, it's a referential equality problem. Your default empty array is not the same reference on every render, which causes instability of the value being returned if the URL is empty.

Try moving your parser definition outside the render body:

const parseAsTypes = parseAsArrayOf(parseAsString).withDefault([])

function useTypes() {
  return useQueryState("types", parseAsTypes);
}

@franky47 franky47 removed the cannot-reproduce Either no reproduction provided, or cannot reproduce with a minimal setup label Mar 26, 2025
@adriandmitroca
Copy link

adriandmitroca commented Mar 26, 2025

Would using JSON.stringify for equality checks be a good approach to handle this within nuqs itself? I can see many React apps overlooking this issue since it’s easy to miss.

@franky47
Copy link
Member

There is no equality check, the default value is returned as passed if the parsed state is null:

https://github.com/47ng/nuqs/blob/next/packages/nuqs/src/useQueryState.ts#L309

You could use this JSON.stringify trick further down in the dependency arrays that consume query states, but the better fix is to ensure stability at the source.

@adriandmitroca
Copy link

Ah right, makes perfect sense in such case.

@shrestha12344
Copy link
Author

Its working after moving parser definition outside the component but I have to provide custom eq as below to remove query from URL when we have []. I have a custom parser using btoa and atob.

  eq(a, b) {
    return JSON.stringify(a) === JSON.stringify(b);
  }

@franky47
Copy link
Member

franky47 commented Mar 28, 2025

That's the correct approach!

We had a suggestion for a base64 conversion utility (see #552), the issue of using atob/btoa is that they don't handle the extended Unicode charset.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants