next.js/packages/next/src/client/components/router-reducer/reducers/find-head-in-cache.ts
find-head-in-cache.ts71 lines2.0 KB
import type {
  FlightRouterState,
  CacheNode,
} from '../../../../shared/lib/app-router-types'
import { DEFAULT_SEGMENT_KEY } from '../../../../shared/lib/segment'
import { createRouterCacheKey } from '../create-router-cache-key'

export function findHeadInCache(
  cache: CacheNode,
  parallelRoutes: FlightRouterState[1]
): [CacheNode, string, string] | null {
  return findHeadInCacheImpl(cache, parallelRoutes, '', '')
}

function findHeadInCacheImpl(
  cache: CacheNode,
  parallelRoutes: FlightRouterState[1],
  keyPrefix: string,
  keyPrefixWithoutSearchParams: string
): [CacheNode, string, string] | null {
  const isLastItem = Object.keys(parallelRoutes).length === 0
  if (isLastItem) {
    // Returns the entire Cache Node of the segment whose head we will render.
    return [cache, keyPrefix, keyPrefixWithoutSearchParams]
  }

  // First try the 'children' parallel route if it exists
  // when starting from the "root", this corresponds with the main page component
  const parallelRoutesKeys = Object.keys(parallelRoutes).filter(
    (key) => key !== 'children'
  )

  // if we are at the root, we need to check the children slot first
  if ('children' in parallelRoutes) {
    parallelRoutesKeys.unshift('children')
  }

  const slots = cache.slots
  if (slots !== null) {
    for (const key of parallelRoutesKeys) {
      const [segment, childParallelRoutes] = parallelRoutes[key]
      // If the parallel is not matched and using the default segment,
      // skip searching the head from it.
      if (segment === DEFAULT_SEGMENT_KEY) {
        continue
      }

      const childCacheNode = slots[key]
      if (!childCacheNode) {
        continue
      }

      const cacheKey = createRouterCacheKey(segment)
      const cacheKeyWithoutSearchParams = createRouterCacheKey(segment, true)

      const item = findHeadInCacheImpl(
        childCacheNode,
        childParallelRoutes,
        keyPrefix + '/' + cacheKey,
        keyPrefix + '/' + cacheKeyWithoutSearchParams
      )

      if (item) {
        return item
      }
    }
  }

  return null
}
Quest for Codev2.0.0
/
SIGN IN