Skip to content

Commit 3c01f23

Browse files
committed
feat: Allow shallow: false updates to reload the page in React SPA
1 parent c23f838 commit 3c01f23

File tree

1 file changed

+52
-11
lines changed

1 file changed

+52
-11
lines changed

packages/nuqs/src/adapters/react.ts

+52-11
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,48 @@
11
import mitt from 'mitt'
2-
import { useEffect, useState } from 'react'
2+
import {
3+
createContext,
4+
createElement,
5+
useContext,
6+
useEffect,
7+
useMemo,
8+
useState,
9+
type ReactNode
10+
} from 'react'
311
import { renderQueryString } from '../url-encoding'
412
import { createAdapterProvider } from './lib/context'
513
import type { AdapterOptions } from './lib/defs'
614
import { patchHistory, type SearchParamsSyncEmitter } from './lib/patch-history'
715

816
const emitter: SearchParamsSyncEmitter = mitt()
917

10-
function updateUrl(search: URLSearchParams, options: AdapterOptions) {
11-
const url = new URL(location.href)
12-
url.search = renderQueryString(search)
13-
const method =
14-
options.history === 'push' ? history.pushState : history.replaceState
15-
method.call(history, history.state, '', url)
16-
emitter.emit('update', search)
17-
if (options.scroll === true) {
18-
window.scrollTo({ top: 0 })
18+
function generateUpdateUrlFn(reloadPageOnShallowFalseUpdates: boolean) {
19+
return function updateUrl(search: URLSearchParams, options: AdapterOptions) {
20+
const url = new URL(location.href)
21+
url.search = renderQueryString(search)
22+
if (reloadPageOnShallowFalseUpdates && options.shallow === false) {
23+
const method =
24+
options.history === 'push' ? location.assign : location.replace
25+
method.call(location, url)
26+
} else {
27+
const method =
28+
options.history === 'push' ? history.pushState : history.replaceState
29+
method.call(history, history.state, '', url)
30+
}
31+
emitter.emit('update', search)
32+
if (options.scroll === true) {
33+
window.scrollTo({ top: 0 })
34+
}
1935
}
2036
}
2137

38+
const NuqsReactAdapterContext = createContext({
39+
reloadPageOnShallowFalseUpdates: false
40+
})
41+
2242
function useNuqsReactAdapter() {
43+
const { reloadPageOnShallowFalseUpdates } = useContext(
44+
NuqsReactAdapterContext
45+
)
2346
const [searchParams, setSearchParams] = useState(() => {
2447
if (typeof location === 'undefined') {
2548
return new URLSearchParams()
@@ -39,13 +62,31 @@ function useNuqsReactAdapter() {
3962
window.removeEventListener('popstate', onPopState)
4063
}
4164
}, [])
65+
const updateUrl = useMemo(
66+
() => generateUpdateUrlFn(reloadPageOnShallowFalseUpdates),
67+
[reloadPageOnShallowFalseUpdates]
68+
)
4269
return {
4370
searchParams,
4471
updateUrl
4572
}
4673
}
4774

48-
export const NuqsAdapter = createAdapterProvider(useNuqsReactAdapter)
75+
const NuqsReactAdapter = createAdapterProvider(useNuqsReactAdapter)
76+
77+
export function NuqsAdapter({
78+
children,
79+
reloadPageOnShallowFalseUpdates = false
80+
}: {
81+
children: ReactNode
82+
reloadPageOnShallowFalseUpdates?: boolean
83+
}) {
84+
return createElement(
85+
NuqsReactAdapterContext.Provider,
86+
{ value: { reloadPageOnShallowFalseUpdates } },
87+
createElement(NuqsReactAdapter, null, children)
88+
)
89+
}
4990

5091
/**
5192
* Opt-in to syncing shallow updates of the URL with the useOptimisticSearchParams hook.

0 commit comments

Comments
 (0)