Skip to content

Commit

Permalink
Add additional comments for reducer/cachenode (#39065)
Browse files Browse the repository at this point in the history
- Add additional comments for reducer functions.
- Add comments for CacheNode



## Bug

- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have helpful link attached, see `contributing.md`

## Feature

- [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR.
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [ ] Errors have helpful link attached, see `contributing.md`

## Documentation / Examples

- [ ] Make sure the linting passes by running `pnpm lint`
- [ ] The examples guidelines are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing.md#adding-examples)
  • Loading branch information
timneutkens committed Jul 27, 2022
1 parent 8fc8a6c commit e647295
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 34 deletions.
87 changes: 63 additions & 24 deletions packages/next/client/components/reducer.ts
Expand Up @@ -7,6 +7,9 @@ import type {
import { matchSegment } from './match-segments'
import { fetchServerResponse } from './app-router.client'

/**
* Fill cache with subTreeData based on flightDataPath
*/
function fillCacheWithNewSubTreeData(
newCache: CacheNode,
existingCache: CacheNode,
Expand Down Expand Up @@ -73,6 +76,9 @@ function fillCacheWithNewSubTreeData(
)
}

/**
* Kick off fetch based on the common layout between two routes. Fill cache with data property holding the in-progress fetch.
*/
function fillCacheWithDataProperty(
newCache: CacheNode,
existingCache: CacheNode,
Expand Down Expand Up @@ -148,6 +154,10 @@ function fillCacheWithDataProperty(
)
}

/**
* Decide if the segments can be optimistically rendered, kicking off the fetch in layout-router.
* - When somewhere in the path to the segment there is a loading.js this becomes true
*/
function canOptimisticallyRender(
segments: string[],
flightRouterState: FlightRouterState
Expand Down Expand Up @@ -186,6 +196,10 @@ function canOptimisticallyRender(
)
}

/**
* Create optimistic version of router state based on the existing router state and segments.
* This is used to allow rendering layout-routers up till the point where data is missing.
*/
function createOptimisticTree(
segments: string[],
flightRouterState: FlightRouterState | null,
Expand Down Expand Up @@ -246,7 +260,10 @@ function createOptimisticTree(
return result
}

function walkTreeWithFlightDataPath(
/**
* Apply the router state from the Flight response. Creates a new router state tree.
*/
function applyRouterStatePatchToTree(
flightSegmentPath: FlightData[0],
flightRouterState: FlightRouterState,
treePatch: FlightRouterState
Expand Down Expand Up @@ -279,7 +296,7 @@ function walkTreeWithFlightDataPath(
...parallelRoutes,
[parallelRouteKey]: lastSegment
? treePatch
: walkTreeWithFlightDataPath(
: applyRouterStatePatchToTree(
flightSegmentPath.slice(2),
parallelRoutes[parallelRouteKey],
treePatch
Expand All @@ -299,32 +316,13 @@ function walkTreeWithFlightDataPath(
return tree
}

type PushRef = {
/**
* If the app-router should push a new history entry in app-router's useEffect()
*/
pendingPush: boolean
/**
* Multi-page navigation through location.href.
*/
mpaNavigation: boolean
}

export type FocusAndScrollRef = {
/**
* If focus and scroll should be set in the layout-router's useEffect()
*/
apply: boolean
}

type AppRouterState = {
tree: FlightRouterState
cache: CacheNode
pushRef: PushRef
focusAndScrollRef: FocusAndScrollRef
canonicalUrl: string
}

export const ACTION_RELOAD = 'reload'
export const ACTION_NAVIGATE = 'navigate'
export const ACTION_RESTORE = 'restore'
Expand Down Expand Up @@ -407,6 +405,47 @@ interface ServerPatchAction {
cache: CacheNode
}

interface PushRef {
/**
* If the app-router should push a new history entry in app-router's useEffect()
*/
pendingPush: boolean
/**
* Multi-page navigation through location.href.
*/
mpaNavigation: boolean
}

/**
* Handles keeping the state of app-router.
*/
type AppRouterState = {
/**
* The router state, this is written into the history state in app-router using replaceState/pushState.
* - Has to be serializable as it is written into the history state.
* - Holds which segments are shown on the screen.
* - Holds where loading states (loading.js) exists.
*/
tree: FlightRouterState
/**
* The cache holds React nodes for every segment that is shown on screen as well as previously shown segments and prefetched segments.
* It also holds in-progress data requests.
*/
cache: CacheNode
/**
* Decides if the update should create a new history entry and if the navigation can't be handled by app-router.
*/
pushRef: PushRef
/**
* Decides if the update should apply scroll and focus management.
*/
focusAndScrollRef: FocusAndScrollRef
/**
* The canonical url that is pushed/replaced
*/
canonicalUrl: string
}

/**
* Reducer that handles the app-router state updates.
*/
Expand Down Expand Up @@ -575,7 +614,7 @@ export function reducer(
const flightSegmentPath = flightDataPath.slice(0, -3)

// Create new tree based on the flightSegmentPath and router state patch
const newTree = walkTreeWithFlightDataPath(
const newTree = applyRouterStatePatchToTree(
// TODO-APP: remove ''
['', ...flightSegmentPath],
state.tree,
Expand Down Expand Up @@ -641,7 +680,7 @@ export function reducer(
const treePath = flightDataPath.slice(0, -3)
const [treePatch] = flightDataPath.slice(-2)

const newTree = walkTreeWithFlightDataPath(
const newTree = applyRouterStatePatchToTree(
// TODO-APP: remove ''
['', ...treePath],
state.tree,
Expand Down Expand Up @@ -726,7 +765,7 @@ export function reducer(

// Given the path can only have two items the items are only the router state and subTreeData for the root.
const [treePatch, subTreeData] = flightDataPath
const newTree = walkTreeWithFlightDataPath(
const newTree = applyRouterStatePatchToTree(
// TODO-APP: remove ''
[''],
state.tree,
Expand Down
38 changes: 29 additions & 9 deletions packages/next/server/app-render.tsx
Expand Up @@ -246,6 +246,9 @@ type DynamicParamTypes = 'catchall' | 'optional-catchall' | 'dynamic'
// d = dynamic
export type DynamicParamTypesShort = 'c' | 'oc' | 'd'

/**
* Shorten the dynamic param in order to make it smaller when transmitted to the browser.
*/
function getShortDynamicParamType(
type: DynamicParamTypes
): DynamicParamTypesShort {
Expand All @@ -261,10 +264,16 @@ function getShortDynamicParamType(
}
}

/**
* Segment in the router state.
*/
export type Segment =
| string
| [param: string, value: string, type: DynamicParamTypesShort]

/**
* LoaderTree is generated in next-app-loader.
*/
type LoaderTree = [
segment: string,
parallelRoutes: { [parallelRouterKey: string]: LoaderTree },
Expand All @@ -275,6 +284,9 @@ type LoaderTree = [
}
]

/**
* Router state
*/
export type FlightRouterState = [
segment: Segment,
parallelRoutes: { [parallelRouterKey: string]: FlightRouterState },
Expand All @@ -283,7 +295,11 @@ export type FlightRouterState = [
loading?: 'loading'
]

/**
* Individual Flight response path
*/
export type FlightSegmentPath =
// Uses `any` as repeating pattern can't be typed.
| any[]
// Looks somewhat like this
| [
Expand All @@ -296,21 +312,25 @@ export type FlightSegmentPath =
]

export type FlightDataPath =
// Uses `any` as repeating pattern can't be typed.
| any[]
// Looks somewhat like this
| [
segment: Segment,
parallelRoute: string,
segment: Segment,
parallelRoute: string,
segment: Segment,
parallelRoute: string,
currentSegment: Segment,
tree: FlightRouterState,
subTreeData: React.ReactNode
// Holds full path to the segment.
...FlightSegmentPath,
/* segment of the rendered slice: */ Segment,
/* treePatch */ FlightRouterState,
/* subTreeData: */ React.ReactNode
]

/**
* The Flight response data
*/
export type FlightData = Array<FlightDataPath> | string

/**
* Property holding the current subTreeData.
*/
export type ChildProp = {
current: React.ReactNode
segment: Segment
Expand Down
14 changes: 13 additions & 1 deletion packages/next/shared/lib/app-router-context.ts
Expand Up @@ -4,11 +4,23 @@ import type { FlightRouterState, FlightData } from '../../server/app-render'

export type ChildSegmentMap = Map<string, CacheNode>

/**
* Cache node used in app-router / layout-router.
*/
export type CacheNode = {
/**
* In-flight request for this node.
*/
data: ReturnType<
typeof import('../../client/components/app-router.client').fetchServerResponse
> | null
subTreeData: null | React.ReactNode
/**
* React Component for this node.
*/
subTreeData: React.ReactNode | null
/**
* Child parallel routes.
*/
parallelRoutes: Map<string, ChildSegmentMap>
}

Expand Down

0 comments on commit e647295

Please sign in to comment.