Skip to content

Commit 9d4b7c2

Browse files
committed
re-apply changes
1 parent bae3b98 commit 9d4b7c2

File tree

2 files changed

+119
-96
lines changed

2 files changed

+119
-96
lines changed

packages/react-router/tests/store-updates-during-navigation.test.tsx

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ describe("Store doesn't update *too many* times during navigation", () => {
110110
// This number should be as small as possible to minimize the amount of work
111111
// that needs to be done during a navigation.
112112
// Any change that increases this number should be investigated.
113-
expect(updates).toBe(17)
113+
expect(updates).toBe(14)
114114
})
115115

116116
test('redirection in preload', async () => {
@@ -128,6 +128,22 @@ describe("Store doesn't update *too many* times during navigation", () => {
128128
// This number should be as small as possible to minimize the amount of work
129129
// that needs to be done during a navigation.
130130
// Any change that increases this number should be investigated.
131-
expect(updates).toBe(8)
131+
expect(updates).toBe(6)
132+
})
133+
134+
test('sync beforeLoad', async () => {
135+
const params = setup({
136+
beforeLoad: () => {},
137+
loader: () => new Promise<void>((resolve) => setTimeout(resolve, 100)),
138+
defaultPendingMs: 100,
139+
defaultPendingMinMs: 300,
140+
})
141+
142+
const updates = await run(params)
143+
144+
// This number should be as small as possible to minimize the amount of work
145+
// that needs to be done during a navigation.
146+
// Any change that increases this number should be investigated.
147+
expect(updates).toBe(14)
132148
})
133149
})

packages/router-core/src/router.ts

Lines changed: 101 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -2318,11 +2318,9 @@ export class RouterCore<
23182318
const match = this.getMatch(matchId)!
23192319
if (shouldPending && match._nonReactive.pendingTimeout === undefined) {
23202320
const pendingTimeout = setTimeout(() => {
2321-
try {
2322-
// Update the match and prematurely resolve the loadMatches promise so that
2323-
// the pending component can start rendering
2324-
this.triggerOnReady(innerLoadContext)
2325-
} catch {}
2321+
// Update the match and prematurely resolve the loadMatches promise so that
2322+
// the pending component can start rendering
2323+
this.triggerOnReady(innerLoadContext)
23262324
}, pendingMs)
23272325
match._nonReactive.pendingTimeout = pendingTimeout
23282326
}
@@ -2371,51 +2369,10 @@ export class RouterCore<
23712369
index: number,
23722370
route: AnyRoute,
23732371
): void | Promise<void> => {
2374-
const resolve = () => {
2375-
innerLoadContext.updateMatch(matchId, (prev) => {
2376-
prev._nonReactive.beforeLoadPromise?.resolve()
2377-
prev._nonReactive.beforeLoadPromise = undefined
2378-
2379-
return {
2380-
...prev,
2381-
isFetching: false,
2382-
}
2383-
})
2384-
}
2385-
2386-
try {
2387-
const match = this.getMatch(matchId)!
2388-
match._nonReactive.beforeLoadPromise = createControlledPromise<void>()
2389-
// explicitly capture the previous loadPromise
2390-
const prevLoadPromise = match._nonReactive.loadPromise
2391-
match._nonReactive.loadPromise = createControlledPromise<void>(() => {
2392-
prevLoadPromise?.resolve()
2393-
})
2394-
2395-
const { paramsError, searchError } = this.getMatch(matchId)!
2396-
2397-
if (paramsError) {
2398-
this.handleSerialError(
2399-
innerLoadContext,
2400-
index,
2401-
paramsError,
2402-
'PARSE_PARAMS',
2403-
)
2404-
}
2405-
2406-
if (searchError) {
2407-
this.handleSerialError(
2408-
innerLoadContext,
2409-
index,
2410-
searchError,
2411-
'VALIDATE_SEARCH',
2412-
)
2413-
}
2414-
2415-
this.setupPendingTimeout(innerLoadContext, matchId, route)
2416-
2417-
const abortController = new AbortController()
2372+
const match = this.getMatch(matchId)!
2373+
const abortController = new AbortController()
24182374

2375+
const pending = () => {
24192376
const parentMatchId = innerLoadContext.matches[index - 1]?.id
24202377
const parentMatch = parentMatchId
24212378
? this.getMatch(parentMatchId)!
@@ -2433,69 +2390,118 @@ export class RouterCore<
24332390
...prev.__routeContext,
24342391
},
24352392
}))
2393+
}
24362394

2437-
const { search, params, context, cause } = this.getMatch(matchId)!
2395+
const resolve = () => {
2396+
match._nonReactive.beforeLoadPromise?.resolve()
2397+
match._nonReactive.beforeLoadPromise = undefined
2398+
innerLoadContext.updateMatch(matchId, (prev) => ({
2399+
...prev,
2400+
isFetching: false,
2401+
}))
2402+
}
24382403

2439-
const preload = this.resolvePreload(innerLoadContext, matchId)
2404+
match._nonReactive.beforeLoadPromise = createControlledPromise<void>()
2405+
// explicitly capture the previous loadPromise
2406+
const prevLoadPromise = match._nonReactive.loadPromise
2407+
match._nonReactive.loadPromise = createControlledPromise<void>(() => {
2408+
prevLoadPromise?.resolve()
2409+
})
24402410

2441-
const beforeLoadFnContext: BeforeLoadContextOptions<
2442-
any,
2443-
any,
2444-
any,
2445-
any,
2446-
any
2447-
> = {
2448-
search,
2449-
abortController,
2450-
params,
2451-
preload,
2452-
context,
2453-
location: innerLoadContext.location,
2454-
navigate: (opts: any) =>
2455-
this.navigate({ ...opts, _fromLocation: innerLoadContext.location }),
2456-
buildLocation: this.buildLocation,
2457-
cause: preload ? 'preload' : cause,
2458-
matches: innerLoadContext.matches,
2459-
}
2411+
const { paramsError, searchError } = this.getMatch(matchId)!
24602412

2461-
const updateContext = (beforeLoadContext: any) => {
2462-
if (isRedirect(beforeLoadContext) || isNotFound(beforeLoadContext)) {
2463-
this.handleSerialError(
2464-
innerLoadContext,
2465-
index,
2466-
beforeLoadContext,
2467-
'BEFORE_LOAD',
2468-
)
2469-
}
2413+
if (paramsError) {
2414+
this.handleSerialError(
2415+
innerLoadContext,
2416+
index,
2417+
paramsError,
2418+
'PARSE_PARAMS',
2419+
)
2420+
}
2421+
2422+
if (searchError) {
2423+
this.handleSerialError(
2424+
innerLoadContext,
2425+
index,
2426+
searchError,
2427+
'VALIDATE_SEARCH',
2428+
)
2429+
}
24702430

2431+
this.setupPendingTimeout(innerLoadContext, matchId, route)
2432+
2433+
// if there is no `beforeLoad` option, skip everything, batch update the store, return early
2434+
if (!route.options.beforeLoad) {
2435+
batch(() => {
2436+
pending()
2437+
resolve()
2438+
})
2439+
return
2440+
}
2441+
2442+
pending()
2443+
2444+
const updateContext = (beforeLoadContext: any) => {
2445+
if (beforeLoadContext === undefined) {
2446+
resolve()
2447+
return
2448+
}
2449+
if (isRedirect(beforeLoadContext) || isNotFound(beforeLoadContext)) {
2450+
this.handleSerialError(
2451+
innerLoadContext,
2452+
index,
2453+
beforeLoadContext,
2454+
'BEFORE_LOAD',
2455+
)
2456+
}
2457+
batch(() => {
24712458
innerLoadContext.updateMatch(matchId, (prev) => ({
24722459
...prev,
24732460
__beforeLoadContext: beforeLoadContext,
24742461
context: {
2475-
...parentMatchContext,
2476-
...prev.__routeContext,
2462+
...prev.context,
24772463
...beforeLoadContext,
24782464
},
2479-
abortController,
24802465
}))
2481-
}
2482-
2483-
const beforeLoadContext = route.options.beforeLoad?.(beforeLoadFnContext)
2466+
resolve()
2467+
})
2468+
}
2469+
const { search, params, context, cause } = this.getMatch(matchId)!
2470+
const preload = this.resolvePreload(innerLoadContext, matchId)
2471+
const beforeLoadFnContext: BeforeLoadContextOptions<
2472+
any,
2473+
any,
2474+
any,
2475+
any,
2476+
any
2477+
> = {
2478+
search,
2479+
abortController,
2480+
params,
2481+
preload,
2482+
context,
2483+
location: innerLoadContext.location,
2484+
navigate: (opts: any) =>
2485+
this.navigate({
2486+
...opts,
2487+
_fromLocation: innerLoadContext.location,
2488+
}),
2489+
buildLocation: this.buildLocation,
2490+
cause: preload ? 'preload' : cause,
2491+
matches: innerLoadContext.matches,
2492+
}
2493+
try {
2494+
const beforeLoadContext = route.options.beforeLoad(beforeLoadFnContext)
24842495
if (isPromise(beforeLoadContext)) {
2485-
return beforeLoadContext
2486-
.then(updateContext)
2487-
.catch((err) => {
2488-
this.handleSerialError(innerLoadContext, index, err, 'BEFORE_LOAD')
2489-
})
2490-
.then(resolve)
2496+
return beforeLoadContext.then(updateContext).catch((err) => {
2497+
this.handleSerialError(innerLoadContext, index, err, 'BEFORE_LOAD')
2498+
})
24912499
} else {
24922500
updateContext(beforeLoadContext)
24932501
}
24942502
} catch (err) {
24952503
this.handleSerialError(innerLoadContext, index, err, 'BEFORE_LOAD')
24962504
}
2497-
2498-
resolve()
24992505
return
25002506
}
25012507

@@ -2709,7 +2715,8 @@ export class RouterCore<
27092715
} catch (e) {
27102716
let error = e
27112717

2712-
await this.potentialPendingMinPromise(matchId)
2718+
const pendingPromise = this.potentialPendingMinPromise(matchId)
2719+
if (pendingPromise) await pendingPromise
27132720

27142721
this.handleRedirectAndNotFound(
27152722
innerLoadContext,

0 commit comments

Comments
 (0)