next.js/packages/next/src/client/components/router-reducer/reducers/server-patch-reducer.ts
server-patch-reducer.ts68 lines2.3 KB
import { createHrefFromUrl } from '../create-href-from-url'
import {
  ACTION_REFRESH,
  type ServerPatchAction,
  type ReducerState,
  type ReadonlyReducerState,
  ScrollBehavior,
} from '../router-reducer-types'
import {
  completeHardNavigation,
  navigateToKnownRoute,
} from '../../segment-cache/navigation'
import { refreshReducer } from './refresh-reducer'
import { FreshnessPolicy } from '../ppr-navigations'

export function serverPatchReducer(
  state: ReadonlyReducerState,
  action: ServerPatchAction
): ReducerState {
  // A "retry" is a navigation that happens due to a route mismatch. It's
  // similar to a refresh, because we will omit any existing dynamic data on
  // the page. But we seed the retry navigation with the exact tree that the
  // server just responded with.
  const retryMpa = action.mpa
  const retryUrl = new URL(action.url, location.origin)
  const retrySeed = action.seed
  const navigateType = action.navigateType
  if (retryMpa || retrySeed === null) {
    // If the server did not send back data during the mismatch, fall back to
    // an MPA navigation.
    return completeHardNavigation(state, retryUrl, navigateType)
  }
  const currentUrl = new URL(state.canonicalUrl, location.origin)
  const currentRenderedSearch = state.renderedSearch
  if (action.previousTree !== state.tree) {
    // There was another, more recent navigation since the once that
    // mismatched. We can abort the retry, but we still need to refresh the
    // page to evict any stale dynamic data.
    return refreshReducer(state, { type: ACTION_REFRESH })
  }
  // There have been no new navigations since the mismatched one. Refresh,
  // using the tree we just received from the server.
  const retryCanonicalUrl = createHrefFromUrl(retryUrl)
  const retryNextUrl = action.nextUrl
  const scrollBehavior = ScrollBehavior.Default
  const now = Date.now()
  return navigateToKnownRoute(
    now,
    state,
    retryUrl,
    retryCanonicalUrl,
    retrySeed,
    currentUrl,
    currentRenderedSearch,
    state.cache,
    state.tree,
    FreshnessPolicy.RefreshAll,
    retryNextUrl,
    scrollBehavior,
    navigateType,
    null,
    // Server patch (retry) navigations don't use route prediction. This is
    // typically a retry after a previous mismatch, so the route was already
    // marked as having a dynamic rewrite when the mismatch was detected.
    null
  )
}
Quest for Codev2.0.0
/
SIGN IN