Skip to content

Commit 7b446d3

Browse files
committed
ref: Pure internal state init function (#633)
- Follow the Rules of React to init the query ref once on mount - Remove access to the queued value, doesn't seem to change outcome of issue 359
1 parent 5bc7bfe commit 7b446d3

File tree

4 files changed

+16
-22
lines changed

4 files changed

+16
-22
lines changed

packages/e2e/cypress/e2e/repro-359.cy.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ it('repro-359', () => {
1111
cy.get('#nuqss-component').should('have.text', '')
1212

1313
cy.contains('Component 1 (nuqs)').click()
14-
cy.wait(100)
14+
// cy.wait(100)
1515
cy.location('search').should('eq', '?param=comp1&component=comp1')
1616
cy.get('#comp1').should('have.text', 'comp1')
1717
cy.get('#comp2').should('not.exist')
@@ -21,7 +21,7 @@ it('repro-359', () => {
2121
cy.get('#nuqss-component').should('have.text', 'comp1')
2222

2323
cy.contains('Component 2 (nuqs)').click()
24-
cy.wait(100)
24+
// cy.wait(100)
2525
cy.location('search').should('eq', '?param=comp2&component=comp2')
2626
cy.get('#comp1').should('not.exist')
2727
cy.get('#comp2').should('have.text', 'comp2')
@@ -31,7 +31,7 @@ it('repro-359', () => {
3131
cy.get('#nuqss-component').should('have.text', 'comp2')
3232

3333
cy.contains('Component 1 (nuq+)').click()
34-
cy.wait(100)
34+
// cy.wait(100)
3535
cy.location('search').should('eq', '?param=comp1&component=comp1')
3636
cy.get('#comp1').should('have.text', 'comp1')
3737
cy.get('#comp2').should('not.exist')
@@ -41,7 +41,7 @@ it('repro-359', () => {
4141
cy.get('#nuqss-component').should('have.text', 'comp1')
4242

4343
cy.contains('Component 2 (nuq+)').click()
44-
cy.wait(100)
44+
// cy.wait(100)
4545
cy.location('search').should('eq', '?param=comp2&component=comp2')
4646
cy.get('#comp1').should('not.exist')
4747
cy.get('#comp2').should('have.text', 'comp2')

packages/nuqs/src/update-queue.ts

-4
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,6 @@ export function enqueueQueryStringUpdate<Value>(
5757
return serializedOrNull
5858
}
5959

60-
export function getQueuedValue(key: string) {
61-
return updateQueue.get(key) ?? null
62-
}
63-
6460
/**
6561
* Eventually flush the update queue to the URL query string.
6662
*

packages/nuqs/src/useQueryState.ts

+5-7
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { emitter, type CrossHookSyncPayload } from './sync'
77
import {
88
FLUSH_RATE_LIMIT_MS,
99
enqueueQueryStringUpdate,
10-
getQueuedValue,
1110
scheduleFlushToURL
1211
} from './update-queue'
1312
import { safeParse } from './utils'
@@ -225,13 +224,12 @@ export function useQueryState<T = string>(
225224
const router = useRouter()
226225
// Not reactive, but available on the server and on page load
227226
const initialSearchParams = useSearchParams()
228-
const queryRef = React.useRef<string | null>(null)
227+
const queryRef = React.useRef<string | null>(
228+
initialSearchParams?.get(key) ?? null
229+
)
229230
const [internalState, setInternalState] = React.useState<T | null>(() => {
230-
const queueValue = getQueuedValue(key)
231-
const urlValue = initialSearchParams?.get(key) ?? null
232-
const value = queueValue ?? urlValue
233-
queryRef.current = value
234-
return value === null ? null : safeParse(parse, value, key)
231+
const query = initialSearchParams?.get(key) ?? null
232+
return query === null ? null : safeParse(parse, query, key)
235233
})
236234
const stateRef = React.useRef(internalState)
237235
debug(

packages/nuqs/src/useQueryStates.ts

+7-7
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import { emitter, type CrossHookSyncPayload } from './sync'
1111
import {
1212
FLUSH_RATE_LIMIT_MS,
1313
enqueueQueryStringUpdate,
14-
getQueuedValue,
1514
scheduleFlushToURL
1615
} from './update-queue'
1716
import { safeParse } from './utils'
@@ -94,9 +93,13 @@ export function useQueryStates<KeyMap extends UseQueryStatesKeysMap>(
9493
// Not reactive, but available on the server and on page load
9594
const initialSearchParams = useSearchParams()
9695
const queryRef = React.useRef<Record<string, string | null>>({})
96+
// Initialise the queryRef with the initial values
97+
if (Object.keys(queryRef.current).length !== Object.keys(keyMap).length) {
98+
queryRef.current = Object.fromEntries(initialSearchParams?.entries() ?? [])
99+
}
100+
97101
const [internalState, setInternalState] = React.useState<V>(() => {
98102
const source = initialSearchParams ?? new URLSearchParams()
99-
queryRef.current = Object.fromEntries(source.entries())
100103
return parseMap(keyMap, urlKeys, source)
101104
})
102105

@@ -120,8 +123,7 @@ export function useQueryStates<KeyMap extends UseQueryStatesKeysMap>(
120123
}, [
121124
Object.keys(resolvedUrlKeys)
122125
.map(key => initialSearchParams?.get(key))
123-
.join('&'),
124-
stateKeys
126+
.join('&')
125127
])
126128

127129
// Sync all hooks together & with external URL changes
@@ -253,9 +255,7 @@ function parseMap<KeyMap extends UseQueryStatesKeysMap>(
253255
return Object.keys(keyMap).reduce((obj, stateKey) => {
254256
const urlKey = urlKeys?.[stateKey] ?? stateKey
255257
const { defaultValue, parse } = keyMap[stateKey]!
256-
const urlQuery = searchParams?.get(urlKey) ?? null
257-
const queueQuery = getQueuedValue(urlKey)
258-
const query = queueQuery ?? urlQuery
258+
const query = searchParams?.get(urlKey) ?? null
259259
if (cachedQuery && cachedState && cachedQuery[urlKey] === query) {
260260
obj[stateKey as keyof KeyMap] =
261261
cachedState[stateKey] ?? defaultValue ?? null

0 commit comments

Comments
 (0)