|
1 | 1 | 'use client' |
2 | 2 |
|
| 3 | +import type { ParsedUrlQuery } from 'querystring' |
| 4 | +import { InvariantError } from '../../shared/lib/invariant-error' |
| 5 | + |
| 6 | +import type { Params } from '../../server/request/params' |
| 7 | + |
| 8 | +/** |
| 9 | + * When the Page is a client component we send the params and searchParams to this client wrapper |
| 10 | + * where they are turned into dynamically tracked values before being passed to the actual Page component. |
| 11 | + * |
| 12 | + * additionally we may send promises representing the params and searchParams. We don't ever use these passed |
| 13 | + * values but it can be necessary for the sender to send a Promise that doesn't resolve in certain situations. |
| 14 | + * It is up to the caller to decide if the promises are needed. |
| 15 | + */ |
3 | 16 | export function ClientPageRoot({ |
4 | 17 | Component, |
5 | | - props, |
| 18 | + searchParams, |
| 19 | + params, |
| 20 | + // eslint-disable-next-line @typescript-eslint/no-unused-vars |
| 21 | + promises, |
6 | 22 | }: { |
7 | 23 | Component: React.ComponentType<any> |
8 | | - props: { [props: string]: any } |
| 24 | + searchParams: ParsedUrlQuery |
| 25 | + params: Params |
| 26 | + promises?: Array<Promise<any>> |
9 | 27 | }) { |
10 | 28 | if (typeof window === 'undefined') { |
11 | | - const { createDynamicallyTrackedParams } = |
12 | | - require('../../server/request/fallback-params') as typeof import('../../server/request/fallback-params') |
13 | | - const { createDynamicallyTrackedSearchParams } = |
14 | | - require('../../server/request/search-params') as typeof import('../../server/request/search-params') |
15 | | - |
16 | | - // We expect to be passed searchParams but even if we aren't we can construct one from |
17 | | - // an empty object. We only do this if we are in a static generation as a performance |
18 | | - // optimization. Ideally we'd unconditionally construct the tracked params but since |
19 | | - // this creates a proxy which is slow and this would happen even for client navigations |
20 | | - // that are done entirely dynamically and we know there the dynamic tracking is a noop |
21 | | - // in this dynamic case we can safely elide it. |
22 | | - props.searchParams = createDynamicallyTrackedSearchParams( |
23 | | - props.searchParams || {} |
24 | | - ) |
25 | | - props.params = props.params |
26 | | - ? createDynamicallyTrackedParams(props.params) |
27 | | - : {} |
| 29 | + const { staticGenerationAsyncStorage } = |
| 30 | + require('./static-generation-async-storage.external') as typeof import('./static-generation-async-storage.external') |
| 31 | + |
| 32 | + let clientSearchParams: Promise<ParsedUrlQuery> |
| 33 | + let clientParams: Promise<Params> |
| 34 | + // We are going to instrument the searchParams prop with tracking for the |
| 35 | + // appropriate context. We wrap differently in prerendering vs rendering |
| 36 | + const store = staticGenerationAsyncStorage.getStore() |
| 37 | + if (!store) { |
| 38 | + throw new InvariantError( |
| 39 | + 'Expected staticGenerationStore to exist when handling searchParams in a client Page.' |
| 40 | + ) |
| 41 | + } |
| 42 | + |
| 43 | + if (store.isStaticGeneration) { |
| 44 | + // We are in a prerender context |
| 45 | + const { createPrerenderSearchParamsFromClient } = |
| 46 | + require('../../server/request/search-params') as typeof import('../../server/request/search-params') |
| 47 | + clientSearchParams = createPrerenderSearchParamsFromClient(store) |
| 48 | + |
| 49 | + const { createPrerenderParamsFromClient } = |
| 50 | + require('../../server/request/params') as typeof import('../../server/request/params') |
| 51 | + |
| 52 | + clientParams = createPrerenderParamsFromClient(params, store) |
| 53 | + } else { |
| 54 | + const { createRenderSearchParamsFromClient } = |
| 55 | + require('../../server/request/search-params') as typeof import('../../server/request/search-params') |
| 56 | + clientSearchParams = createRenderSearchParamsFromClient( |
| 57 | + searchParams, |
| 58 | + store |
| 59 | + ) |
| 60 | + const { createRenderParamsFromClient } = |
| 61 | + require('../../server/request/params') as typeof import('../../server/request/params') |
| 62 | + clientParams = createRenderParamsFromClient(params, store) |
| 63 | + } |
| 64 | + |
| 65 | + return <Component params={clientParams} searchParams={clientSearchParams} /> |
| 66 | + } else { |
| 67 | + const { createRenderSearchParamsFromClient } = |
| 68 | + require('../../server/request/search-params.browser') as typeof import('../../server/request/search-params.browser') |
| 69 | + const clientSearchParams = createRenderSearchParamsFromClient(searchParams) |
| 70 | + const { createRenderParamsFromClient } = |
| 71 | + require('../../server/request/params.browser') as typeof import('../../server/request/params.browser') |
| 72 | + const clientParams = createRenderParamsFromClient(params) |
| 73 | + |
| 74 | + return <Component params={clientParams} searchParams={clientSearchParams} /> |
28 | 75 | } |
29 | | - return <Component {...props} /> |
30 | 76 | } |
0 commit comments