Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add additional item to RSC payload, preparing for head.tsx on navigation #42791

Merged
merged 5 commits into from Nov 14, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 3 additions & 3 deletions packages/next/client/components/app-router.tsx
Expand Up @@ -180,7 +180,7 @@ function Router({
previousTree,
overrideCanonicalUrl,
cache: {
status: CacheStates.LAZYINITIALIZED,
status: CacheStates.LAZY_INITIALIZED,
data: null,
subTreeData: null,
parallelRoutes: new Map(),
Expand All @@ -206,7 +206,7 @@ function Router({
forceOptimisticNavigation,
navigateType,
cache: {
status: CacheStates.LAZYINITIALIZED,
status: CacheStates.LAZY_INITIALIZED,
data: null,
subTreeData: null,
parallelRoutes: new Map(),
Expand Down Expand Up @@ -268,7 +268,7 @@ function Router({

// TODO-APP: revisit if this needs to be passed.
cache: {
status: CacheStates.LAZYINITIALIZED,
status: CacheStates.LAZY_INITIALIZED,
data: null,
subTreeData: null,
parallelRoutes: new Map(),
Expand Down
4 changes: 2 additions & 2 deletions packages/next/client/components/layout-router.tsx
Expand Up @@ -146,7 +146,7 @@ export function InnerLayoutRouter({
// TODO-APP: verify if this can be null based on user code
childProp.current !== null
) {
if (childNode && childNode.status === CacheStates.LAZYINITIALIZED) {
if (childNode && childNode.status === CacheStates.LAZY_INITIALIZED) {
// @ts-expect-error TODO-APP: handle changing of the type
childNode.status = CacheStates.READY
// @ts-expect-error TODO-APP: handle changing of the type
Expand Down Expand Up @@ -181,7 +181,7 @@ export function InnerLayoutRouter({
* Flight data fetch kicked off during render and put into the cache.
*/
childNodes.set(path, {
status: CacheStates.DATAFETCH,
status: CacheStates.DATA_FETCH,
data: fetchServerResponse(new URL(url, location.origin), refetchTree),
subTreeData: null,
parallelRoutes: new Map(),
Expand Down
45 changes: 25 additions & 20 deletions packages/next/client/components/reducer.ts
Expand Up @@ -35,8 +35,10 @@ function createRecordFromThenable(thenable: any) {
/**
* Read record value or throw Promise if it's not resolved yet.
*/
function readRecordValue(thenable: any) {
function readRecordValue<T>(thenable: Promise<T>): T {
// @ts-expect-error TODO: fix type
if (thenable.status === 'fulfilled') {
// @ts-expect-error TODO: fix type
return thenable.value
} else {
throw thenable
Expand Down Expand Up @@ -97,7 +99,7 @@ function fillLazyItemsTillLeafWithHead(
let parallelRouteCacheNode = new Map(existingParallelRoutesCacheNode)
parallelRouteCacheNode.delete(cacheKey)
const newCacheNode: CacheNode = {
status: CacheStates.LAZYINITIALIZED,
status: CacheStates.LAZY_INITIALIZED,
data: null,
subTreeData: null,
parallelRoutes: new Map(),
Expand All @@ -116,7 +118,7 @@ function fillLazyItemsTillLeafWithHead(
}

const newCacheNode: CacheNode = {
status: CacheStates.LAZYINITIALIZED,
status: CacheStates.LAZY_INITIALIZED,
data: null,
subTreeData: null,
parallelRoutes: new Map(),
Expand All @@ -139,7 +141,7 @@ function fillCacheWithNewSubTreeData(
existingCache: CacheNode,
flightDataPath: FlightDataPath
): void {
const isLastEntry = flightDataPath.length <= 4
const isLastEntry = flightDataPath.length <= 5
const [parallelRouteKey, segment] = flightDataPath

const segmentForCache = Array.isArray(segment) ? segment[1] : segment
Expand Down Expand Up @@ -290,7 +292,7 @@ function fillCacheWithPrefetchedSubTreeData(
existingCache: CacheNode,
flightDataPath: FlightDataPath
): void {
const isLastEntry = flightDataPath.length <= 4
const isLastEntry = flightDataPath.length <= 5
const [parallelRouteKey, segment] = flightDataPath

const segmentForCache = Array.isArray(segment) ? segment[1] : segment
Expand Down Expand Up @@ -370,7 +372,7 @@ function fillCacheWithDataProperty(
childCacheNode === existingChildCacheNode
) {
childSegmentMap.set(segment, {
status: CacheStates.DATAFETCH,
status: CacheStates.DATA_FETCH,
data: fetchResponse(),
subTreeData: null,
parallelRoutes: new Map(),
Expand All @@ -383,7 +385,7 @@ function fillCacheWithDataProperty(
// Start fetch in the place where the existing cache doesn't have the data yet.
if (!childCacheNode) {
childSegmentMap.set(segment, {
status: CacheStates.DATAFETCH,
status: CacheStates.DATA_FETCH,
data: fetchResponse(),
subTreeData: null,
parallelRoutes: new Map(),
Expand Down Expand Up @@ -972,7 +974,7 @@ function clientReducer(
}

// Unwrap cache data with `use` to suspend here (in the reducer) until the fetch resolves.
const [flightData, canonicalUrlOverride] = readRecordValue(cache.data)
const [flightData, canonicalUrlOverride] = readRecordValue(cache.data!)

// Handle case when navigating to page in `pages` from `app`
if (typeof flightData === 'string') {
Expand All @@ -995,10 +997,11 @@ function clientReducer(
const flightDataPath = flightData[0]

// The one before last item is the router state tree patch
const [treePatch, subTreeData] = flightDataPath.slice(-2)
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [treePatch, subTreeData, head] = flightDataPath.slice(-3)

// Path without the last segment, router state, and the subTreeData
const flightSegmentPath = flightDataPath.slice(0, -3)
const flightSegmentPath = flightDataPath.slice(0, -4)
hanneslund marked this conversation as resolved.
Show resolved Hide resolved

// Create new tree based on the flightSegmentPath and router state patch
const newTree = applyRouterStatePatchToTree(
Expand All @@ -1022,7 +1025,7 @@ function clientReducer(
mutable.patchedTree = newTree
mutable.mpaNavigation = isNavigatingToNewRootLayout(state.tree, newTree)

if (flightDataPath.length === 2) {
if (flightDataPath.length === 3) {
cache.subTreeData = subTreeData
} else {
// Copy subTreeData for the root node of the cache.
Expand Down Expand Up @@ -1119,13 +1122,14 @@ function clientReducer(
// TODO-APP: Currently the Flight data can only have one item but in the future it can have multiple paths.
const flightDataPath = flightData[0]

// Slices off the last segment (which is at -3) as it doesn't exist in the tree yet
const treePath = flightDataPath.slice(0, -3)
const [treePatch, subTreeData] = flightDataPath.slice(-2)
// Slices off the last segment (which is at -4) as it doesn't exist in the tree yet
const flightSegmentPath = flightDataPath.slice(0, -4)
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [treePatch, subTreeData, head] = flightDataPath.slice(-3)

const newTree = applyRouterStatePatchToTree(
// TODO-APP: remove ''
['', ...treePath],
['', ...flightSegmentPath],
state.tree,
treePatch
)
Expand All @@ -1146,7 +1150,7 @@ function clientReducer(
mutable.mpaNavigation = isNavigatingToNewRootLayout(state.tree, newTree)

// Root refresh
if (flightDataPath.length === 2) {
if (flightDataPath.length === 3) {
cache.subTreeData = subTreeData
} else {
// Copy subTreeData for the root node of the cache.
Expand Down Expand Up @@ -1244,7 +1248,7 @@ function clientReducer(
])
)
}
const [flightData, canonicalUrlOverride] = readRecordValue(cache.data)
const [flightData, canonicalUrlOverride] = readRecordValue(cache.data!)

// Handle case when navigating to page in `pages` from `app`
if (typeof flightData === 'string') {
Expand All @@ -1265,7 +1269,7 @@ function clientReducer(
const flightDataPath = flightData[0]

// FlightDataPath with more than two items means unexpected Flight data was returned
if (flightDataPath.length !== 2) {
if (flightDataPath.length !== 3) {
// TODO-APP: handle this case better
console.log('REFRESH FAILED')
return state
Expand Down Expand Up @@ -1330,15 +1334,16 @@ function clientReducer(
const flightDataPath = flightData[0]

// The one before last item is the router state tree patch
const [treePatch, subTreeData] = flightDataPath.slice(-2)
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [treePatch, subTreeData, head] = flightDataPath.slice(-3)

// TODO-APP: Verify if `null` can't be returned from user code.
// If subTreeData is null the prefetch did not provide a component tree.
if (subTreeData !== null) {
fillCacheWithPrefetchedSubTreeData(state.cache, flightDataPath)
}

const flightSegmentPath = flightDataPath.slice(0, -2)
const flightSegmentPath = flightDataPath.slice(0, -3)

const newTree = applyRouterStatePatchToTree(
// TODO-APP: remove ''
Expand Down
3 changes: 3 additions & 0 deletions packages/next/server/app-render.tsx
Expand Up @@ -1425,6 +1425,9 @@ export async function renderToHTMLOrFlight(
)
).Component
),
isPrefetch && !Boolean(loaderTreeToFilter[2].loading) ? null : (
<>{null}</> // TODO: change this to head tags.
),
]
}

Expand Down
8 changes: 4 additions & 4 deletions packages/next/shared/lib/app-router-context.ts
Expand Up @@ -8,8 +8,8 @@ export type ChildSegmentMap = Map<string, CacheNode>

// eslint-disable-next-line no-shadow
export enum CacheStates {
LAZYINITIALIZED = 'LAZYINITIALIZED',
DATAFETCH = 'DATAFETCH',
LAZY_INITIALIZED = 'LAZYINITIALIZED',
DATA_FETCH = 'DATAFETCH',
READY = 'READY',
}

Expand All @@ -18,7 +18,7 @@ export enum CacheStates {
*/
export type CacheNode =
| {
status: CacheStates.DATAFETCH
status: CacheStates.DATA_FETCH
/**
* In-flight request for this node.
*/
Expand Down Expand Up @@ -52,7 +52,7 @@ export type CacheNode =
parallelRoutes: Map<string, ChildSegmentMap>
}
| {
status: CacheStates.LAZYINITIALIZED
status: CacheStates.LAZY_INITIALIZED
data: null
head?: React.ReactNode
subTreeData: null
Expand Down