-
Notifications
You must be signed in to change notification settings - Fork 28k
/
Copy pathapp-router-context.shared-runtime.ts
186 lines (163 loc) · 5.42 KB
/
app-router-context.shared-runtime.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
'use client'
import type {
FocusAndScrollRef,
PrefetchKind,
RouterChangeByServerResponse,
} from '../../client/components/router-reducer/router-reducer-types'
import type { FetchServerResponseResult } from '../../client/components/router-reducer/fetch-server-response'
import type { FlightRouterState } from '../../server/app-render/types'
import React from 'react'
export type ChildSegmentMap = Map<string, CacheNode>
/**
* Cache node used in app-router / layout-router.
*/
export type CacheNode = ReadyCacheNode | LazyCacheNode
export type LoadingModuleData =
| [React.JSX.Element, React.ReactNode, React.ReactNode]
| null
export type LazyCacheNode = {
/**
* Whether the lazy cache node data promise has been resolved.
* This value is only true after we've called `use` on the promise (and applied the data to the tree).
*/
lazyDataResolved: boolean
/**
* When rsc is null, this is a lazily-initialized cache node.
*
* If the app attempts to render it, it triggers a lazy data fetch,
* postpones the render, and schedules an update to a new tree.
*
* TODO: This mechanism should not be used when PPR is enabled, though it
* currently is in some cases until we've implemented partial
* segment fetching.
*/
rsc: null
/**
* A prefetched version of the segment data. See explanation in corresponding
* field of ReadyCacheNode (below).
*
* Since LazyCacheNode mostly only exists in the non-PPR implementation, this
* will usually be null, but it could have been cloned from a previous
* CacheNode that was created by the PPR implementation. Eventually we want
* to migrate everything away from LazyCacheNode entirely.
*/
prefetchRsc: React.ReactNode
/**
* A pending response for the lazy data fetch. If this is not present
* during render, it is lazily created.
*/
lazyData: Promise<FetchServerResponseResult> | null
prefetchHead: React.ReactNode
head: React.ReactNode
prefetchLayerAssets: React.ReactNode
layerAssets: React.ReactNode
loading: LoadingModuleData
/**
* Child parallel routes.
*/
parallelRoutes: Map<string, ChildSegmentMap>
}
export type ReadyCacheNode = {
/**
* Whether the lazy cache node data promise has been resolved.
* This value is only true after we've called `use` on the promise (and applied the data to the tree).
*/
lazyDataResolved: boolean
/**
* When rsc is not null, it represents the RSC data for the
* corresponding segment.
*
* `null` is a valid React Node but because segment data is always a
* <LayoutRouter> component, we can use `null` to represent empty.
*
* TODO: For additional type safety, update this type to
* Exclude<React.ReactNode, null>. Need to update createEmptyCacheNode to
* accept rsc as an argument, or just inline the callers.
*/
rsc: React.ReactNode
/**
* Represents a static version of the segment that can be shown immediately,
* and may or may not contain dynamic holes. It's prefetched before a
* navigation occurs.
*
* During rendering, we will choose whether to render `rsc` or `prefetchRsc`
* with `useDeferredValue`. As with the `rsc` field, a value of `null` means
* no value was provided. In this case, the LayoutRouter will go straight to
* rendering the `rsc` value; if that one is also missing, it will suspend and
* trigger a lazy fetch.
*/
prefetchRsc: React.ReactNode
/**
* There should never be a lazy data request in this case.
*/
lazyData: null
prefetchHead: React.ReactNode
head: React.ReactNode
prefetchLayerAssets: React.ReactNode
layerAssets: React.ReactNode
loading: LoadingModuleData
parallelRoutes: Map<string, ChildSegmentMap>
}
export interface NavigateOptions {
scroll?: boolean
}
export interface PrefetchOptions {
kind: PrefetchKind
}
export interface AppRouterInstance {
/**
* Navigate to the previous history entry.
*/
back(): void
/**
* Navigate to the next history entry.
*/
forward(): void
/**
* Refresh the current page.
*/
refresh(): void
/**
* Refresh the current page. Use in development only.
* @internal
*/
fastRefresh(): void
/**
* Navigate to the provided href.
* Pushes a new history entry.
*/
push(href: string, options?: NavigateOptions): void
/**
* Navigate to the provided href.
* Replaces the current history entry.
*/
replace(href: string, options?: NavigateOptions): void
/**
* Prefetch the provided href.
*/
prefetch(href: string, options?: PrefetchOptions): void
}
export const AppRouterContext = React.createContext<AppRouterInstance | null>(
null
)
export const LayoutRouterContext = React.createContext<{
childNodes: CacheNode['parallelRoutes']
tree: FlightRouterState
url: string
loading: LoadingModuleData
} | null>(null)
export const GlobalLayoutRouterContext = React.createContext<{
buildId: string
tree: FlightRouterState
changeByServerResponse: RouterChangeByServerResponse
focusAndScrollRef: FocusAndScrollRef
nextUrl: string | null
}>(null as any)
export const TemplateContext = React.createContext<React.ReactNode>(null as any)
if (process.env.NODE_ENV !== 'production') {
AppRouterContext.displayName = 'AppRouterContext'
LayoutRouterContext.displayName = 'LayoutRouterContext'
GlobalLayoutRouterContext.displayName = 'GlobalLayoutRouterContext'
TemplateContext.displayName = 'TemplateContext'
}
export const MissingSlotContext = React.createContext<Set<string>>(new Set())