Skip to content

Commit ecf24b5

Browse files
committed
fix: context
1 parent ee0874f commit ecf24b5

File tree

5 files changed

+49
-24
lines changed

5 files changed

+49
-24
lines changed

packages/react-router/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
"jsdom": "^24.1.1",
7878
"react": "^18.2.0",
7979
"react-dom": "^18.2.0",
80+
"vitest": "^1.6.0",
8081
"zod": "^3.23.8"
8182
},
8283
"peerDependencies": {

packages/react-router/src/Matches.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ export interface RouteMatch<
5252
beforeLoadData?: unknown
5353
loaderPromise?: ControlledPromise<void>
5454
loaderData?: TLoaderData
55+
__routeContext: Record<string, unknown>
56+
__beforeLoadContext: Record<string, unknown>
5557
context: TAllContext
5658
search: TFullSearchSchema
5759
fetchCount: number

packages/react-router/src/route.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -913,8 +913,8 @@ export class Route<
913913

914914
const isRoot = !options?.path && !options?.id
915915

916-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
917-
this.parentRoute = this.options.getParentRoute()
916+
// eslint-disable-next-line ts/no-unnecessary-condition
917+
this.parentRoute = this.options.getParentRoute?.()
918918

919919
if (isRoot) {
920920
this.path = rootRouteId as TPath

packages/react-router/src/router.ts

Lines changed: 41 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -692,7 +692,7 @@ export class Router<
692692
}
693693

694694
if (
695-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
695+
// eslint-disable-next-line ts/no-unnecessary-condition
696696
!this.history ||
697697
(this.options.history && this.options.history !== this.history)
698698
) {
@@ -711,7 +711,7 @@ export class Router<
711711
this.buildRouteTree()
712712
}
713713

714-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
714+
// eslint-disable-next-line ts/no-unnecessary-condition
715715
if (!this.__store) {
716716
this.__store = new Store(getInitialRouterState(this.latestLocation), {
717717
onUpdate: () => {
@@ -1132,7 +1132,9 @@ export class Router<
11321132
isFetching: false,
11331133
error: undefined,
11341134
paramsError: parseErrors[index],
1135-
context: undefined!,
1135+
__routeContext: {},
1136+
__beforeLoadContext: {},
1137+
context: {},
11361138
abortController: new AbortController(),
11371139
fetchCount: 0,
11381140
cause,
@@ -1176,13 +1178,13 @@ export class Router<
11761178
const parentMatchId = parentMatch?.id
11771179

11781180
const parentContext = !parentMatchId
1179-
? ((this.options.context as any) ?? {})
1180-
: (parentMatch.context ?? this.options.context ?? {})
1181+
? (this.options.context as any) ?? {}
1182+
: parentMatch.context ?? this.options.context ?? {}
11811183

1182-
// Ingest the new parent context
11831184
match.context = {
1184-
...match.context,
11851185
...parentContext,
1186+
...match.__routeContext,
1187+
...match.__beforeLoadContext,
11861188
}
11871189

11881190
// Update the match's context
@@ -1197,10 +1199,13 @@ export class Router<
11971199
}
11981200

11991201
// Get the route context
1200-
const context = route.options.context?.(contextFnContext) ?? {}
1202+
match.__routeContext = route.options.context?.(contextFnContext) ?? {}
12011203

1202-
// Ingest the new route context
1203-
match.context = { ...match.context, ...context }
1204+
match.context = {
1205+
...parentContext,
1206+
...match.__routeContext,
1207+
...match.__beforeLoadContext,
1208+
}
12041209

12051210
matches.push(match)
12061211
})
@@ -1574,7 +1579,10 @@ export class Router<
15741579
let redirect: ResolvedRedirect | undefined
15751580
let notFound: NotFoundError | undefined
15761581

1577-
const loadPromise = new Promise<void>((resolve) => {
1582+
let loadPromise: Promise<void>
1583+
1584+
// eslint-disable-next-line prefer-const
1585+
loadPromise = new Promise<void>((resolve) => {
15781586
this.startReactTransition(async () => {
15791587
try {
15801588
const next = this.latestLocation
@@ -1627,9 +1635,9 @@ export class Router<
16271635
await this.loadMatches({
16281636
matches: pendingMatches,
16291637
location: next,
1630-
// eslint-disable-next-line @typescript-eslint/require-await
1638+
// eslint-disable-next-line ts/require-await
16311639
onReady: async () => {
1632-
// eslint-disable-next-line @typescript-eslint/require-await
1640+
// eslint-disable-next-line ts/require-await
16331641
this.startViewTransition(async () => {
16341642
// this.viewTransitionPromise = createControlledPromise<true>()
16351643

@@ -1893,6 +1901,7 @@ export class Router<
18931901

18941902
for (const [index, { id: matchId, routeId }] of matches.entries()) {
18951903
const existingMatch = this.getMatch(matchId)!
1904+
const parentMatchId = matches[index - 1]?.id
18961905

18971906
if (
18981907
// If we are in the middle of a load, either of these will be present
@@ -1954,12 +1963,22 @@ export class Router<
19541963
handleSerialError(index, searchError, 'VALIDATE_SEARCH')
19551964
}
19561965

1966+
const getParentMatchContext = () =>
1967+
parentMatchId
1968+
? this.getMatch(parentMatchId)!.context
1969+
: this.options.context ?? {}
1970+
19571971
updateMatch(matchId, (prev) => ({
19581972
...prev,
19591973
isFetching: 'beforeLoad',
19601974
fetchCount: prev.fetchCount + 1,
19611975
abortController,
19621976
pendingTimeout,
1977+
context: {
1978+
...getParentMatchContext(),
1979+
...prev.__routeContext,
1980+
...prev.__beforeLoadContext,
1981+
},
19631982
}))
19641983

19651984
const { search, params, context, cause } =
@@ -1993,8 +2012,9 @@ export class Router<
19932012
return {
19942013
...prev,
19952014
context: {
1996-
...prev.context,
1997-
beforeLoadContext,
2015+
...getParentMatchContext(),
2016+
...prev.__routeContext,
2017+
...beforeLoadContext,
19982018
},
19992019
abortController,
20002020
}
@@ -2058,12 +2078,12 @@ export class Router<
20582078
const age = Date.now() - this.getMatch(matchId)!.updatedAt
20592079

20602080
const staleAge = preload
2061-
? (route.options.preloadStaleTime ??
2081+
? route.options.preloadStaleTime ??
20622082
this.options.defaultPreloadStaleTime ??
2063-
30_000) // 30 seconds for preloads by default
2064-
: (route.options.staleTime ??
2083+
30_000 // 30 seconds for preloads by default
2084+
: route.options.staleTime ??
20652085
this.options.defaultStaleTime ??
2066-
0)
2086+
0
20672087

20682088
const shouldReloadOption = route.options.shouldReload
20692089

@@ -2310,9 +2330,8 @@ export class Router<
23102330
// otherwise, use the gcTime
23112331
const gcTime =
23122332
(d.preload
2313-
? (route.options.preloadGcTime ??
2314-
this.options.defaultPreloadGcTime)
2315-
: (route.options.gcTime ?? this.options.defaultGcTime)) ??
2333+
? route.options.preloadGcTime ?? this.options.defaultPreloadGcTime
2334+
: route.options.gcTime ?? this.options.defaultGcTime) ??
23162335
5 * 60 * 1000
23172336

23182337
return d.status !== 'error' && Date.now() - d.updatedAt < gcTime

pnpm-lock.yaml

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)