next.js/packages/next/src/client/components/router-reducer/is-navigating-to-new-root-layout.ts
is-navigating-to-new-root-layout.ts59 lines2.1 KB
import type { FlightRouterState } from '../../../shared/lib/app-router-types'
import { PrefetchHint } from '../../../shared/lib/app-router-types'
import type { RouteTree } from '../segment-cache/cache'

export function isNavigatingToNewRootLayout(
  currentTree: FlightRouterState,
  nextTree: RouteTree
): boolean {
  // Compare segments
  const currentTreeSegment = currentTree[0]
  const nextTreeSegment = nextTree.segment

  // If any segment is different before we find the root layout, the root layout has changed.
  // E.g. /same/(group1)/layout.js -> /same/(group2)/layout.js
  // First segment is 'same' for both, keep looking. (group1) changed to (group2) before the root layout was found, it must have changed.
  if (Array.isArray(currentTreeSegment) && Array.isArray(nextTreeSegment)) {
    // Compare dynamic param name and type but ignore the value, different values would not affect the current root layout
    // /[name] - /slug1 and /slug2, both values (slug1 & slug2) still has the same layout /[name]/layout.js
    if (
      currentTreeSegment[0] !== nextTreeSegment[0] ||
      currentTreeSegment[2] !== nextTreeSegment[2]
    ) {
      return true
    }
  } else if (currentTreeSegment !== nextTreeSegment) {
    return true
  }

  // Current tree root layout found
  const currentIsRootLayout =
    ((currentTree[4] ?? 0) & PrefetchHint.IsRootLayout) !== 0
  const nextIsRootLayout =
    (nextTree.prefetchHints & PrefetchHint.IsRootLayout) !== 0
  if (currentIsRootLayout) {
    // If the next tree doesn't have the root layout flag, it must have changed.
    return !nextIsRootLayout
  }
  // Current tree didn't have its root layout here, must have changed.
  if (nextIsRootLayout) {
    return true
  }

  const slots = nextTree.slots
  const currentTreeChildren = currentTree[1]
  if (slots !== null) {
    for (const slot in slots) {
      const nextTreeChild = slots[slot]
      const currentTreeChild = currentTreeChildren[slot]
      if (
        currentTreeChild === undefined ||
        isNavigatingToNewRootLayout(currentTreeChild, nextTreeChild)
      ) {
        return true
      }
    }
  }
  return false
}
Quest for Codev2.0.0
/
SIGN IN