diff --git a/packages/e2e/next/cypress/e2e/repro-774.cy.js b/packages/e2e/next/cypress/e2e/repro-774.cy.js
new file mode 100644
index 000000000..bde2d78d6
--- /dev/null
+++ b/packages/e2e/next/cypress/e2e/repro-774.cy.js
@@ -0,0 +1,17 @@
+///
+
+describe('repro-774', () => {
+ it('updates internal state on navigation', () => {
+ cy.visit('/app/repro-774')
+ cy.contains('#hydration-marker', 'hydrated').should('be.hidden')
+ cy.get('#trigger-a').click()
+ cy.get('#value-a').should('have.text', 'a')
+ cy.get('#value-b').should('be.empty')
+ cy.get('#link').click()
+ cy.get('#value-a').should('be.empty')
+ cy.get('#value-b').should('be.empty')
+ cy.get('#trigger-b').click()
+ cy.get('#value-a').should('be.empty')
+ cy.get('#value-b').should('have.text', 'b')
+ })
+})
diff --git a/packages/e2e/next/src/app/app/repro-774/page.tsx b/packages/e2e/next/src/app/app/repro-774/page.tsx
new file mode 100644
index 000000000..ed90cdf39
--- /dev/null
+++ b/packages/e2e/next/src/app/app/repro-774/page.tsx
@@ -0,0 +1,41 @@
+'use client'
+
+import Link from 'next/link'
+import { parseAsString, useQueryStates } from 'nuqs'
+import { Suspense } from 'react'
+
+export default function Home() {
+ return (
+ <>
+
+
+
+
+ >
+ )
+}
+
+const searchParams = {
+ a: parseAsString.withDefault(''),
+ b: parseAsString.withDefault('')
+}
+
+function Client() {
+ const [{ a, b }, setSearchParams] = useQueryStates(searchParams)
+ return (
+ <>
+
+
+ {a}
+ {b}
+ >
+ )
+}
diff --git a/packages/nuqs/src/useQueryStates.ts b/packages/nuqs/src/useQueryStates.ts
index 6ece5c74f..849e7315a 100644
--- a/packages/nuqs/src/useQueryStates.ts
+++ b/packages/nuqs/src/useQueryStates.ts
@@ -133,6 +133,7 @@ export function useQueryStates(
queryRef.current,
stateRef.current
)
+ stateRef.current = state
setInternalState(state)
}, [
Object.values(resolvedUrlKeys)
@@ -274,7 +275,7 @@ function parseMap(
cachedQuery?: Record,
cachedState?: NullableValues
): NullableValues {
- return Object.keys(keyMap).reduce((obj, stateKey) => {
+ return Object.keys(keyMap).reduce((out, stateKey) => {
const urlKey = urlKeys?.[stateKey] ?? stateKey
const { parse } = keyMap[stateKey]!
const queuedQuery = getQueuedValue(urlKey)
@@ -283,15 +284,15 @@ function parseMap(
? (searchParams?.get(urlKey) ?? null)
: queuedQuery
if (cachedQuery && cachedState && cachedQuery[urlKey] === query) {
- obj[stateKey as keyof KeyMap] = cachedState[stateKey] ?? null
- return obj
+ out[stateKey as keyof KeyMap] = cachedState[stateKey] ?? null
+ return out
}
const value = query === null ? null : safeParse(parse, query, stateKey)
- obj[stateKey as keyof KeyMap] = value ?? null
+ out[stateKey as keyof KeyMap] = value ?? null
if (cachedQuery) {
cachedQuery[urlKey] = query
}
- return obj
+ return out
}, {} as NullableValues)
}