nuqs icon indicating copy to clipboard operation
nuqs copied to clipboard

On navigation, Next.js renders the target page with the source URL state

Open l0gicgate opened this issue 2 months ago • 11 comments

Context

What's your version of nuqs?

2.7.0

What framework are you using?

  • ✅ Next.js (app router)

Which version of your framework are you using?

Next v15.5.4

Description

When transitioning between routes, nuqs now holds previous route query parameters in state.

Reproduction

  1. Navigate to route 1 (using NextLink), set some query parameters
  2. Navigate to route 2 (using NextLink), the query parameters from route 1 are present when the route transition is complete and they should not be present.

This does not occur on v2.6.0

Use case:

I'm navigating between 2 views which both have a table bound to the query parameters. I have sortField=X which only applies to Table 1, then I navigate to other page with Table 2 where sortField=X does not apply the page breaks as the state is invalid.

I think this PR broke it: https://github.com/47ng/nuqs/pull/1143

l0gicgate avatar Oct 02 '25 02:10 l0gicgate

Thanks for the report, I'm looking into it.

franky47 avatar Oct 02 '25 03:10 franky47

I can't reproduce it with this setup:

'use client'

import { useQueryState } from 'nuqs'
import { Display } from '../components/display'
import Link from 'next/link'

type Repro1156PageAProps = {
  pageBPath: string
}

export function Repro1156PageA({ pageBPath }: Repro1156PageAProps) {
  const [state, setState] = useQueryState('test')
  return (
    <>
      <button onClick={() => setState('pass')}>Set state</button>
      <Link href={pageBPath}>Navigate</Link>
      <Display environment="client" state={state} />
    </>
  )
}

export function Repro1156PageB() {
  const [state] = useQueryState('test')
  return <Display environment="client" state={state} />
}

Is there anything else you do in your code that might be relevant?

franky47 avatar Oct 02 '25 03:10 franky47

Here is a repo with the repro and here's a screenshot of the behavior:

https://github.com/l0gicgate/nuqs-issue-1156

To reproduce

  1. bun i && bun run dev
  2. Open http://localhost:3000
  3. Open console
  4. Click on "Set query"
  5. Then click on "Go to Page 2"
  6. Look at the console output

state1 from page 1 should never bleed into state2 on page 2

Image

l0gicgate avatar Oct 02 '25 05:10 l0gicgate

Thanks for the reproduction, I see the same behaviour on [email protected] though.

Next.js renders the destination page in the background on navigation, and since the useQueryState(s) hooks see the URL as the source of truth (it hasn't changed yet while navigation is pending), they'd use the old state temporarily, until the URL updates to the new page, and the state follows that (returning null).

IIRC React Router & Remix also behave like this and there is an issue about this behaviour: #947.

franky47 avatar Oct 02 '25 05:10 franky47

With 2.6.0 it is not the same, hence why my app breaks.

Here is the output:

Image

l0gicgate avatar Oct 02 '25 14:10 l0gicgate

For what it's worth, I was getting errors that I am attributing this as well. Reverting to 2.6.0 solved the problem for me.

felix-quotez avatar Nov 14 '25 10:11 felix-quotez

I'm seeing this happen in v2.5-v2.5.2 too

lpbonomi avatar Nov 18 '25 18:11 lpbonomi

I incorrectly thought 2.6.0 would not suffer from this, but it does. I now reverted back all the way to 2.4.3, which seems to be working for me.

(edit: ugh, my bad please ignore "The bug appears to be related to navigating to a prefetched route. I can log the value of useSearchParams and it's empty for the new route, yet useQueryStates return the params from the previous route.")

(Next.js 16, React 19.2 with React Compiler enabled.)

felix-quotez avatar Nov 19 '25 19:11 felix-quotez

I tried with the above repo https://github.com/l0gicgate/nuqs-issue-1156 (just in GitHub code spaces) and was able to see the difference in behavior. With 2.4.3 the page does not render with the search params from the previous page.

felix-quotez avatar Nov 19 '25 21:11 felix-quotez

I'm seeing this happen in 2.8.1 too

pimentellima avatar Nov 23 '25 04:11 pimentellima

Seeing this happen with 2.8.1, 2.8.5 as well. Definitely seems like a regression

sunwrobert avatar Dec 17 '25 02:12 sunwrobert