Skip to content

Commit

Permalink
fix: Always update local URL first, then RSC
Browse files Browse the repository at this point in the history
This is because relying only on the Next.js router for
URL updates makes it dependent on the RSC payload
to resolve, which is not the case in some situations:
- Offline or poor network connection
- Requests waterfalling when updating too quickly

Instead, the browser's history API is used for state management,
and optionally on non-shallow updates we can tell the server
about the updated URL to re-render and stream in RSC payloads.
  • Loading branch information
franky47 committed Nov 1, 2023
1 parent e002303 commit 2f8fa79
Showing 1 changed file with 20 additions and 22 deletions.
42 changes: 20 additions & 22 deletions packages/next-usequerystate/src/update-queue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,29 +140,27 @@ function flushUpdateQueue(router: Router) {
const url = query ? `?${query}${hash}` : `${path}${hash}`
debug('[nuqs queue] Updating url: %s', url)
try {
if (options.shallow) {
const updateUrl =
options.history === 'push'
? window.history.pushState
: window.history.replaceState
updateUrl.call(
window.history,
window.history.state,
// Our own updates have a marker to prevent syncing
// when the URL changes (we've already sync'd them up
// via `emitter.emit(key, newValue)` above, without
// going through the parsers).
NOSYNC_MARKER,
url
)
if (options.scroll) {
window.scrollTo(0, 0)
}
} else {
// First, update the URL locally without triggering a network request,
// this allows keeping a reactive URL if the network is slow.
const updateMethod =
options.history === 'push' ? history.pushState : history.replaceState
updateMethod.call(
history,
history.state,
// Our own updates have a marker to prevent syncing
// when the URL changes (we've already sync'd them up
// via `emitter.emit(key, newValue)` above, without
// going through the parsers).
NOSYNC_MARKER,
url
)
if (options.scroll) {
window.scrollTo(0, 0)
}
if (!options.shallow) {
// Call the Next.js router to perform a network request
const updateUrl =
options.history === 'push' ? router.push : router.replace
updateUrl.call(router, url, { scroll: options.scroll })
// and re-render server components.
router.replace(url, { scroll: false })
}
return search
} catch (error) {
Expand Down

0 comments on commit 2f8fa79

Please sign in to comment.