Skip to content

Commit

Permalink
ref: Pure internal state init function (#633)
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
franky47 authored Sep 9, 2024
1 parent 9e54b47 commit 97a1ea8
Show file tree
Hide file tree
Showing 4 changed files with 16 additions and 22 deletions.
8 changes: 4 additions & 4 deletions packages/e2e/cypress/e2e/repro-359.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ it('repro-359', () => {
cy.get('#nuqss-component').should('have.text', '')

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

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

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

cy.contains('Component 2 (nuq+)').click()
cy.wait(100)
// cy.wait(100)
cy.location('search').should('eq', '?param=comp2&component=comp2')
cy.get('#comp1').should('not.exist')
cy.get('#comp2').should('have.text', 'comp2')
Expand Down
4 changes: 0 additions & 4 deletions packages/nuqs/src/update-queue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,6 @@ export function enqueueQueryStringUpdate<Value>(
return serializedOrNull
}

export function getQueuedValue(key: string) {
return updateQueue.get(key) ?? null
}

/**
* Eventually flush the update queue to the URL query string.
*
Expand Down
12 changes: 5 additions & 7 deletions packages/nuqs/src/useQueryState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { emitter, type CrossHookSyncPayload } from './sync'
import {
FLUSH_RATE_LIMIT_MS,
enqueueQueryStringUpdate,
getQueuedValue,
scheduleFlushToURL
} from './update-queue'
import { safeParse } from './utils'
Expand Down Expand Up @@ -225,13 +224,12 @@ export function useQueryState<T = string>(
const router = useRouter()
// Not reactive, but available on the server and on page load
const initialSearchParams = useSearchParams()
const queryRef = React.useRef<string | null>(null)
const queryRef = React.useRef<string | null>(
initialSearchParams?.get(key) ?? null
)
const [internalState, setInternalState] = React.useState<T | null>(() => {
const queueValue = getQueuedValue(key)
const urlValue = initialSearchParams?.get(key) ?? null
const value = queueValue ?? urlValue
queryRef.current = value
return value === null ? null : safeParse(parse, value, key)
const query = initialSearchParams?.get(key) ?? null
return query === null ? null : safeParse(parse, query, key)
})
const stateRef = React.useRef(internalState)
debug(
Expand Down
14 changes: 7 additions & 7 deletions packages/nuqs/src/useQueryStates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { emitter, type CrossHookSyncPayload } from './sync'
import {
FLUSH_RATE_LIMIT_MS,
enqueueQueryStringUpdate,
getQueuedValue,
scheduleFlushToURL
} from './update-queue'
import { safeParse } from './utils'
Expand Down Expand Up @@ -74,9 +73,13 @@ export function useQueryStates<KeyMap extends UseQueryStatesKeysMap>(
// Not reactive, but available on the server and on page load
const initialSearchParams = useSearchParams()
const queryRef = React.useRef<Record<string, string | null>>({})
// Initialise the queryRef with the initial values
if (Object.keys(queryRef.current).length !== Object.keys(keyMap).length) {
queryRef.current = Object.fromEntries(initialSearchParams?.entries() ?? [])
}

const [internalState, setInternalState] = React.useState<V>(() => {
const source = initialSearchParams ?? new URLSearchParams()
queryRef.current = Object.fromEntries(source.entries())
return parseMap(keyMap, source)
})

Expand All @@ -99,8 +102,7 @@ export function useQueryStates<KeyMap extends UseQueryStatesKeysMap>(
}, [
Object.keys(keyMap)
.map(key => initialSearchParams?.get(key))
.join('&'),
keys
.join('&')
])

// Sync all hooks together & with external URL changes
Expand Down Expand Up @@ -214,9 +216,7 @@ function parseMap<KeyMap extends UseQueryStatesKeysMap>(
) {
return Object.keys(keyMap).reduce((obj, key) => {
const { defaultValue, parse } = keyMap[key]!
const urlQuery = searchParams?.get(key) ?? null
const queueQuery = getQueuedValue(key)
const query = queueQuery ?? urlQuery
const query = searchParams?.get(key) ?? null
if (cachedQuery && cachedState && cachedQuery[key] === query) {
obj[key as keyof KeyMap] = cachedState[key] ?? defaultValue ?? null
return obj
Expand Down

0 comments on commit 97a1ea8

Please sign in to comment.