next.js/packages/next/src/client/components/client-page.tsx
client-page.tsx73 lines3.1 KB
'use client'

import type { ParsedUrlQuery } from 'querystring'
import type { Params } from '../../server/request/params'
import { LayoutRouterContext } from '../../shared/lib/app-router-context.shared-runtime'
import { use } from 'react'
import { urlSearchParamsToParsedUrlQuery } from '../route-params'
import { SearchParamsContext } from '../../shared/lib/hooks-client-context.shared-runtime'

/**
 * When the Page is a client component we send the params and searchParams to this client wrapper
 * where they are turned into dynamically tracked values before being passed to the actual Page component.
 *
 * additionally we may send promises representing the params and searchParams. We don't ever use these passed
 * values but it can be necessary for the sender to send a Promise that doesn't resolve in certain situations.
 * It is up to the caller to decide if the promises are needed.
 */
export function ClientPageRoot({
  Component,
  serverProvidedParams,
}: {
  Component: React.ComponentType<any>
  serverProvidedParams: null | {
    searchParams: ParsedUrlQuery
    params: Params
    promises: Array<Promise<any>> | null
  }
}) {
  let searchParams: ParsedUrlQuery
  let params: Params
  if (serverProvidedParams !== null) {
    searchParams = serverProvidedParams.searchParams
    params = serverProvidedParams.params
  } else {
    // When Cache Components is enabled, the server does not pass the params as
    // props; they are parsed on the client and passed via context.
    const layoutRouterContext = use(LayoutRouterContext)
    params =
      layoutRouterContext !== null ? layoutRouterContext.parentParams : {}

    // This is an intentional behavior change: when Cache Components is enabled,
    // client segments receive the "canonical" search params, not the
    // rewritten ones. Users should either call useSearchParams directly or pass
    // the rewritten ones in from a Server Component.
    // TODO: Log a deprecation error when this object is accessed
    searchParams = urlSearchParamsToParsedUrlQuery(use(SearchParamsContext)!)
  }

  if (typeof window === 'undefined') {
    let clientSearchParams: Promise<ParsedUrlQuery>
    let clientParams: Promise<Params>

    const { createSearchParamsFromClient } =
      require('../../server/request/search-params') as typeof import('../../server/request/search-params')
    clientSearchParams = createSearchParamsFromClient(searchParams)

    const { createParamsFromClient } =
      require('../../server/request/params') as typeof import('../../server/request/params')
    clientParams = createParamsFromClient(params)

    return <Component params={clientParams} searchParams={clientSearchParams} />
  } else {
    const { createRenderSearchParamsFromClient } =
      require('../request/search-params.browser') as typeof import('../request/search-params.browser')
    const clientSearchParams = createRenderSearchParamsFromClient(searchParams)
    const { createRenderParamsFromClient } =
      require('../request/params.browser') as typeof import('../request/params.browser')
    const clientParams = createRenderParamsFromClient(params)

    return <Component params={clientParams} searchParams={clientSearchParams} />
  }
}
Quest for Codev2.0.0
/
SIGN IN