@tanstack/react-router 0.0.1-beta.273 → 0.0.1-beta.274
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cjs/Matches.js.map +1 -1
- package/build/cjs/RouterProvider.js +9 -6
- package/build/cjs/RouterProvider.js.map +1 -1
- package/build/cjs/index.js +4 -1
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/route.js.map +1 -1
- package/build/cjs/router.js +150 -100
- package/build/cjs/router.js.map +1 -1
- package/build/esm/index.js +157 -103
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +1 -1
- package/build/stats-react.json +353 -353
- package/build/types/Matches.d.ts +2 -2
- package/build/types/RouterProvider.d.ts +1 -1
- package/build/types/route.d.ts +2 -2
- package/build/types/router.d.ts +3 -1
- package/build/umd/index.development.js +159 -106
- package/build/umd/index.development.js.map +1 -1
- package/build/umd/index.production.js +1 -1
- package/build/umd/index.production.js.map +1 -1
- package/package.json +2 -2
- package/src/Matches.tsx +2 -2
- package/src/RouterProvider.tsx +11 -5
- package/src/route.ts +2 -2
- package/src/router.ts +197 -128
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/react-router",
|
|
3
3
|
"author": "Tanner Linsley",
|
|
4
|
-
"version": "0.0.1-beta.
|
|
4
|
+
"version": "0.0.1-beta.274",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "tanstack/router",
|
|
7
7
|
"homepage": "https://tanstack.com/router",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"@tanstack/store": "^0.1.3",
|
|
45
45
|
"tiny-invariant": "^1.3.1",
|
|
46
46
|
"tiny-warning": "^1.0.3",
|
|
47
|
-
"@tanstack/history": "0.0.1-beta.
|
|
47
|
+
"@tanstack/history": "0.0.1-beta.274"
|
|
48
48
|
},
|
|
49
49
|
"scripts": {
|
|
50
50
|
"build": "rollup --config rollup.config.js"
|
package/src/Matches.tsx
CHANGED
|
@@ -39,10 +39,10 @@ export interface RouteMatch<
|
|
|
39
39
|
context: RouteById<TRouteTree, TRouteId>['types']['allContext']
|
|
40
40
|
search: FullSearchSchema<TRouteTree> &
|
|
41
41
|
RouteById<TRouteTree, TRouteId>['types']['fullSearchSchema']
|
|
42
|
-
|
|
42
|
+
fetchCount: number
|
|
43
43
|
shouldReloadDeps: any
|
|
44
44
|
abortController: AbortController
|
|
45
|
-
cause: 'enter' | 'stay'
|
|
45
|
+
cause: 'preload' | 'enter' | 'stay'
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
export type AnyRouteMatch = RouteMatch<any>
|
package/src/RouterProvider.tsx
CHANGED
|
@@ -54,10 +54,14 @@ export type BuildLocationFn<TRouteTree extends AnyRoute> = (
|
|
|
54
54
|
|
|
55
55
|
export type InjectedHtmlEntry = string | (() => Promise<string> | string)
|
|
56
56
|
|
|
57
|
-
export
|
|
57
|
+
export let routerContext = React.createContext<Router<any>>(null!)
|
|
58
58
|
|
|
59
59
|
if (typeof document !== 'undefined') {
|
|
60
|
-
window.__TSR_ROUTER_CONTEXT__
|
|
60
|
+
if (window.__TSR_ROUTER_CONTEXT__) {
|
|
61
|
+
routerContext = window.__TSR_ROUTER_CONTEXT__
|
|
62
|
+
} else {
|
|
63
|
+
window.__TSR_ROUTER_CONTEXT__ = routerContext as any
|
|
64
|
+
}
|
|
61
65
|
}
|
|
62
66
|
|
|
63
67
|
export function RouterProvider<
|
|
@@ -212,9 +216,11 @@ export function getRouteMatch<TRouteTree extends AnyRoute>(
|
|
|
212
216
|
state: RouterState<TRouteTree>,
|
|
213
217
|
id: string,
|
|
214
218
|
): undefined | RouteMatch<TRouteTree> {
|
|
215
|
-
return [
|
|
216
|
-
|
|
217
|
-
|
|
219
|
+
return [
|
|
220
|
+
...state.preloadMatches,
|
|
221
|
+
...(state.pendingMatches ?? []),
|
|
222
|
+
...state.matches,
|
|
223
|
+
].find((d) => d.id === id)
|
|
218
224
|
}
|
|
219
225
|
|
|
220
226
|
export function useRouterState<
|
package/src/route.ts
CHANGED
|
@@ -171,7 +171,7 @@ type BeforeLoadFn<
|
|
|
171
171
|
location: ParsedLocation
|
|
172
172
|
navigate: NavigateFn<AnyRoute>
|
|
173
173
|
buildLocation: BuildLocationFn<AnyRoute>
|
|
174
|
-
cause: 'enter' | 'stay'
|
|
174
|
+
cause: 'preload' | 'enter' | 'stay'
|
|
175
175
|
}) => Promise<TRouteContext> | TRouteContext | void
|
|
176
176
|
|
|
177
177
|
export type UpdatableRouteOptions<
|
|
@@ -268,7 +268,7 @@ export interface LoaderFnContext<
|
|
|
268
268
|
location: ParsedLocation<TFullSearchSchema>
|
|
269
269
|
navigate: (opts: NavigateOptions<AnyRoute>) => Promise<void>
|
|
270
270
|
parentMatchPromise?: Promise<void>
|
|
271
|
-
cause: 'enter' | 'stay'
|
|
271
|
+
cause: 'preload' | 'enter' | 'stay'
|
|
272
272
|
}
|
|
273
273
|
|
|
274
274
|
export type SearchFilter<T, U = T> = (prev: T) => U
|
package/src/router.ts
CHANGED
|
@@ -110,6 +110,7 @@ export interface RouterOptions<
|
|
|
110
110
|
defaultPendingComponent?: RouteComponent
|
|
111
111
|
defaultPendingMs?: number
|
|
112
112
|
defaultPendingMinMs?: number
|
|
113
|
+
defaultPreloadMaxAge?: number
|
|
113
114
|
caseSensitive?: boolean
|
|
114
115
|
routeTree?: TRouteTree
|
|
115
116
|
basepath?: string
|
|
@@ -129,6 +130,7 @@ export interface RouterState<TRouteTree extends AnyRoute = AnyRoute> {
|
|
|
129
130
|
isTransitioning: boolean
|
|
130
131
|
matches: RouteMatch<TRouteTree>[]
|
|
131
132
|
pendingMatches?: RouteMatch<TRouteTree>[]
|
|
133
|
+
preloadMatches: RouteMatch<TRouteTree>[]
|
|
132
134
|
location: ParsedLocation<FullSearchSchema<TRouteTree>>
|
|
133
135
|
resolvedLocation: ParsedLocation<FullSearchSchema<TRouteTree>>
|
|
134
136
|
lastUpdated: number
|
|
@@ -159,7 +161,7 @@ export interface DehydratedRouterState {
|
|
|
159
161
|
|
|
160
162
|
export type DehydratedRouteMatch = Pick<
|
|
161
163
|
RouteMatch,
|
|
162
|
-
'
|
|
164
|
+
'id' | 'status' | 'updatedAt'
|
|
163
165
|
>
|
|
164
166
|
|
|
165
167
|
export interface DehydratedRouter {
|
|
@@ -658,7 +660,7 @@ export class Router<
|
|
|
658
660
|
context: undefined!,
|
|
659
661
|
abortController: new AbortController(),
|
|
660
662
|
shouldReloadDeps: undefined,
|
|
661
|
-
|
|
663
|
+
fetchCount: 0,
|
|
662
664
|
cause,
|
|
663
665
|
}
|
|
664
666
|
|
|
@@ -976,10 +978,20 @@ export class Router<
|
|
|
976
978
|
let latestPromise
|
|
977
979
|
let firstBadMatchIndex: number | undefined
|
|
978
980
|
|
|
979
|
-
const
|
|
981
|
+
const updateMatch = (match: AnyRouteMatch) => {
|
|
982
|
+
const isPreload = this.state.preloadMatches.find((d) => d.id === match.id)
|
|
983
|
+
const isPending = this.state.pendingMatches?.find(
|
|
984
|
+
(d) => d.id === match.id,
|
|
985
|
+
)
|
|
986
|
+
const matchesKey = isPreload
|
|
987
|
+
? 'preloadMatches'
|
|
988
|
+
: isPending
|
|
989
|
+
? 'pendingMatches'
|
|
990
|
+
: 'matches'
|
|
991
|
+
|
|
980
992
|
this.__store.setState((s) => ({
|
|
981
993
|
...s,
|
|
982
|
-
|
|
994
|
+
[matchesKey]: s[matchesKey]?.map((d) =>
|
|
983
995
|
d.id === match.id ? match : d,
|
|
984
996
|
),
|
|
985
997
|
}))
|
|
@@ -1043,7 +1055,7 @@ export class Router<
|
|
|
1043
1055
|
navigate: (opts) =>
|
|
1044
1056
|
this.navigate({ ...opts, from: match.pathname } as any),
|
|
1045
1057
|
buildLocation: this.buildLocation,
|
|
1046
|
-
cause: match.cause,
|
|
1058
|
+
cause: preload ? 'preload' : match.cause,
|
|
1047
1059
|
})) ?? ({} as any)
|
|
1048
1060
|
|
|
1049
1061
|
if (isRedirect(beforeLoadContext)) {
|
|
@@ -1083,7 +1095,7 @@ export class Router<
|
|
|
1083
1095
|
|
|
1084
1096
|
validResolvedMatches.forEach((match, index) => {
|
|
1085
1097
|
matchPromises.push(
|
|
1086
|
-
(async () => {
|
|
1098
|
+
new Promise<void>(async (resolve) => {
|
|
1087
1099
|
const parentMatchPromise = matchPromises[index - 1]
|
|
1088
1100
|
const route = this.looseRoutesById[match.routeId]!
|
|
1089
1101
|
|
|
@@ -1101,126 +1113,129 @@ export class Router<
|
|
|
1101
1113
|
|
|
1102
1114
|
matches[index] = match = {
|
|
1103
1115
|
...match,
|
|
1104
|
-
fetchedAt: Date.now(),
|
|
1105
1116
|
showPending: false,
|
|
1106
1117
|
}
|
|
1107
1118
|
|
|
1119
|
+
let didShowPending = false
|
|
1108
1120
|
const pendingMs =
|
|
1109
1121
|
route.options.pendingMs ?? this.options.defaultPendingMs
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
if (
|
|
1122
|
+
const pendingMinMs =
|
|
1123
|
+
route.options.pendingMinMs ?? this.options.defaultPendingMinMs
|
|
1124
|
+
const shouldPending =
|
|
1114
1125
|
!preload &&
|
|
1115
1126
|
pendingMs &&
|
|
1116
1127
|
(route.options.pendingComponent ??
|
|
1117
1128
|
this.options.defaultPendingComponent)
|
|
1118
|
-
) {
|
|
1119
|
-
pendingPromise = new Promise((r) => setTimeout(r, pendingMs))
|
|
1120
|
-
}
|
|
1121
|
-
|
|
1122
|
-
if (match.isFetching) {
|
|
1123
|
-
loadPromise = getRouteMatch(this.state, match.id)?.loadPromise
|
|
1124
|
-
} else {
|
|
1125
|
-
const loaderContext: LoaderFnContext = {
|
|
1126
|
-
params: match.params,
|
|
1127
|
-
search: match.search,
|
|
1128
|
-
preload: !!preload,
|
|
1129
|
-
parentMatchPromise,
|
|
1130
|
-
abortController: match.abortController,
|
|
1131
|
-
context: match.context,
|
|
1132
|
-
location: this.state.location,
|
|
1133
|
-
navigate: (opts) =>
|
|
1134
|
-
this.navigate({ ...opts, from: match.pathname } as any),
|
|
1135
|
-
cause: match.cause,
|
|
1136
|
-
}
|
|
1137
|
-
|
|
1138
|
-
// Default to reloading the route all the time
|
|
1139
|
-
let shouldReload = true
|
|
1140
1129
|
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1130
|
+
const fetch = async () => {
|
|
1131
|
+
if (match.isFetching) {
|
|
1132
|
+
loadPromise = getRouteMatch(this.state, match.id)?.loadPromise
|
|
1133
|
+
} else {
|
|
1134
|
+
const loaderContext: LoaderFnContext = {
|
|
1135
|
+
params: match.params,
|
|
1136
|
+
search: match.search,
|
|
1137
|
+
preload: !!preload,
|
|
1138
|
+
parentMatchPromise,
|
|
1139
|
+
abortController: match.abortController,
|
|
1140
|
+
context: match.context,
|
|
1141
|
+
location: this.state.location,
|
|
1142
|
+
navigate: (opts) =>
|
|
1143
|
+
this.navigate({ ...opts, from: match.pathname } as any),
|
|
1144
|
+
cause: preload ? 'preload' : match.cause,
|
|
1145
|
+
}
|
|
1145
1146
|
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1147
|
+
// Default to reloading the route all the time
|
|
1148
|
+
let shouldLoad = true
|
|
1149
|
+
|
|
1150
|
+
const shouldReloadFn = route.options.shouldReload
|
|
1151
|
+
|
|
1152
|
+
let shouldReloadDeps =
|
|
1153
|
+
typeof shouldReloadFn === 'function'
|
|
1154
|
+
? shouldReloadFn(loaderContext)
|
|
1155
|
+
: !!(shouldReloadFn ?? true)
|
|
1156
|
+
|
|
1157
|
+
const compareDeps = () => {
|
|
1158
|
+
if (typeof shouldReloadDeps === 'object') {
|
|
1159
|
+
// compare the deps to see if they've changed
|
|
1160
|
+
shouldLoad = !deepEqual(
|
|
1161
|
+
shouldReloadDeps,
|
|
1162
|
+
match.shouldReloadDeps,
|
|
1163
|
+
)
|
|
1164
|
+
} else {
|
|
1165
|
+
shouldLoad = !!shouldReloadDeps
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1155
1168
|
|
|
1156
|
-
|
|
1169
|
+
// If it's the first preload, or the route is entering, or we're
|
|
1170
|
+
// invalidating, we definitely need to load the route
|
|
1171
|
+
if (invalidate) {
|
|
1172
|
+
// Change nothing, we need to load the route
|
|
1173
|
+
} else if (preload) {
|
|
1174
|
+
if (!match.fetchCount) {
|
|
1175
|
+
// Change nothing, we need to preload the route
|
|
1176
|
+
} else {
|
|
1177
|
+
compareDeps()
|
|
1178
|
+
}
|
|
1179
|
+
} else if (match.cause === 'enter') {
|
|
1180
|
+
if (!match.fetchCount) {
|
|
1181
|
+
// Change nothing, we 100% need to load the route
|
|
1182
|
+
} else {
|
|
1183
|
+
compareDeps()
|
|
1184
|
+
}
|
|
1157
1185
|
} else {
|
|
1158
|
-
|
|
1186
|
+
compareDeps()
|
|
1159
1187
|
}
|
|
1160
|
-
}
|
|
1161
|
-
|
|
1162
|
-
// If the user doesn't want the route to reload, just
|
|
1163
|
-
// resolve with the existing loader data
|
|
1164
1188
|
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
...match,
|
|
1171
|
-
isFetching: true,
|
|
1189
|
+
if (typeof shouldReloadDeps === 'object') {
|
|
1190
|
+
matches[index] = match = {
|
|
1191
|
+
...match,
|
|
1192
|
+
shouldReloadDeps,
|
|
1193
|
+
}
|
|
1172
1194
|
}
|
|
1173
1195
|
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
const component = route.options[type]
|
|
1177
|
-
|
|
1178
|
-
if ((component as any)?.preload) {
|
|
1179
|
-
await (component as any).preload()
|
|
1180
|
-
}
|
|
1181
|
-
}),
|
|
1182
|
-
)
|
|
1183
|
-
|
|
1184
|
-
const loaderPromise = route.options.loader?.(loaderContext)
|
|
1196
|
+
// If the user doesn't want the route to reload, just
|
|
1197
|
+
// resolve with the existing loader data
|
|
1185
1198
|
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1199
|
+
if (!shouldLoad) {
|
|
1200
|
+
loadPromise = Promise.resolve(match.loaderData)
|
|
1201
|
+
} else {
|
|
1202
|
+
if (match.fetchCount && match.status === 'success') {
|
|
1203
|
+
resolve()
|
|
1204
|
+
}
|
|
1192
1205
|
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1206
|
+
// Otherwise, load the route
|
|
1207
|
+
matches[index] = match = {
|
|
1208
|
+
...match,
|
|
1209
|
+
isFetching: true,
|
|
1210
|
+
fetchCount: match.fetchCount + 1,
|
|
1211
|
+
}
|
|
1197
1212
|
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1213
|
+
const componentsPromise = Promise.all(
|
|
1214
|
+
componentTypes.map(async (type) => {
|
|
1215
|
+
const component = route.options[type]
|
|
1201
1216
|
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1217
|
+
if ((component as any)?.preload) {
|
|
1218
|
+
await (component as any).preload()
|
|
1219
|
+
}
|
|
1220
|
+
}),
|
|
1221
|
+
)
|
|
1205
1222
|
|
|
1206
|
-
|
|
1207
|
-
// If the route has a pending component and a pendingMs option,
|
|
1208
|
-
// forcefully show the pending component
|
|
1209
|
-
if (pendingPromise) {
|
|
1210
|
-
pendingPromise.then(() => {
|
|
1211
|
-
if ((latestPromise = checkLatest())) return
|
|
1223
|
+
const loaderPromise = route.options.loader?.(loaderContext)
|
|
1212
1224
|
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1225
|
+
loadPromise = Promise.all([
|
|
1226
|
+
componentsPromise,
|
|
1227
|
+
loaderPromise,
|
|
1228
|
+
]).then((d) => d[1])
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1218
1231
|
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1232
|
+
matches[index] = match = {
|
|
1233
|
+
...match,
|
|
1234
|
+
loadPromise,
|
|
1222
1235
|
}
|
|
1223
1236
|
|
|
1237
|
+
updateMatch(match)
|
|
1238
|
+
|
|
1224
1239
|
try {
|
|
1225
1240
|
const loaderData = await loadPromise
|
|
1226
1241
|
if ((latestPromise = checkLatest())) return await latestPromise
|
|
@@ -1267,22 +1282,44 @@ export class Router<
|
|
|
1267
1282
|
// we already moved the pendingMatches to the matches
|
|
1268
1283
|
// state, so we need to update that specific match
|
|
1269
1284
|
if (didShowPending && pendingMinMs && match.showPending) {
|
|
1270
|
-
|
|
1271
|
-
...s,
|
|
1272
|
-
matches: s.matches?.map((d) =>
|
|
1273
|
-
d.id === match.id ? match : d,
|
|
1274
|
-
),
|
|
1275
|
-
}))
|
|
1285
|
+
updateMatch(match)
|
|
1276
1286
|
}
|
|
1277
1287
|
}
|
|
1278
1288
|
|
|
1279
|
-
|
|
1280
|
-
|
|
1289
|
+
updateMatch(match)
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
if (match.fetchCount && match.status === 'success') {
|
|
1293
|
+
// Background Fetching
|
|
1294
|
+
fetch()
|
|
1295
|
+
} else {
|
|
1296
|
+
// Critical Fetching
|
|
1297
|
+
|
|
1298
|
+
// If we need to potentially show the pending component,
|
|
1299
|
+
// start a timer to show it after the pendingMs
|
|
1300
|
+
if (shouldPending) {
|
|
1301
|
+
new Promise((r) => setTimeout(r, pendingMs)).then(async () => {
|
|
1302
|
+
if ((latestPromise = checkLatest())) return latestPromise
|
|
1303
|
+
|
|
1304
|
+
didShowPending = true
|
|
1305
|
+
matches[index] = match = {
|
|
1306
|
+
...match,
|
|
1307
|
+
showPending: true,
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
updateMatch(match)
|
|
1311
|
+
resolve()
|
|
1312
|
+
})
|
|
1281
1313
|
}
|
|
1282
1314
|
|
|
1283
|
-
|
|
1284
|
-
}
|
|
1285
|
-
|
|
1315
|
+
await fetch()
|
|
1316
|
+
}
|
|
1317
|
+
|
|
1318
|
+
resolve()
|
|
1319
|
+
// No Fetching
|
|
1320
|
+
|
|
1321
|
+
resolve()
|
|
1322
|
+
}),
|
|
1286
1323
|
)
|
|
1287
1324
|
})
|
|
1288
1325
|
|
|
@@ -1312,24 +1349,36 @@ export class Router<
|
|
|
1312
1349
|
pathChanged: pathDidChange,
|
|
1313
1350
|
})
|
|
1314
1351
|
|
|
1315
|
-
|
|
1316
|
-
let pendingMatches: RouteMatch<any, any>[] = this.matchRoutes(
|
|
1317
|
-
next.pathname,
|
|
1318
|
-
next.search,
|
|
1319
|
-
{
|
|
1320
|
-
debug: true,
|
|
1321
|
-
},
|
|
1322
|
-
)
|
|
1323
|
-
|
|
1352
|
+
let pendingMatches!: RouteMatch<any, any>[]
|
|
1324
1353
|
const previousMatches = this.state.matches
|
|
1325
1354
|
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1355
|
+
this.__store.batch(() => {
|
|
1356
|
+
this.__store.setState((s) => ({
|
|
1357
|
+
...s,
|
|
1358
|
+
preloadMatches: s.preloadMatches.filter((d) => {
|
|
1359
|
+
return (
|
|
1360
|
+
Date.now() - d.updatedAt <
|
|
1361
|
+
(this.options.defaultPreloadMaxAge ?? 3000)
|
|
1362
|
+
)
|
|
1363
|
+
}),
|
|
1364
|
+
}))
|
|
1365
|
+
|
|
1366
|
+
// Match the routes
|
|
1367
|
+
pendingMatches = this.matchRoutes(next.pathname, next.search, {
|
|
1368
|
+
debug: true,
|
|
1369
|
+
})
|
|
1370
|
+
|
|
1371
|
+
// Ingest the new matches
|
|
1372
|
+
this.__store.setState((s) => ({
|
|
1373
|
+
...s,
|
|
1374
|
+
isLoading: true,
|
|
1375
|
+
location: next,
|
|
1376
|
+
pendingMatches,
|
|
1377
|
+
preloadMatches: s.preloadMatches.filter((d) => {
|
|
1378
|
+
return !pendingMatches.find((e) => e.id === d.id)
|
|
1379
|
+
}),
|
|
1380
|
+
}))
|
|
1381
|
+
})
|
|
1333
1382
|
|
|
1334
1383
|
try {
|
|
1335
1384
|
try {
|
|
@@ -1411,6 +1460,25 @@ export class Router<
|
|
|
1411
1460
|
throwOnError: true,
|
|
1412
1461
|
})
|
|
1413
1462
|
|
|
1463
|
+
const loadedMatchIds = Object.fromEntries(
|
|
1464
|
+
[
|
|
1465
|
+
...this.state.matches,
|
|
1466
|
+
...(this.state.pendingMatches ?? []),
|
|
1467
|
+
...this.state.preloadMatches,
|
|
1468
|
+
]?.map((d) => [d.id, true]),
|
|
1469
|
+
)
|
|
1470
|
+
|
|
1471
|
+
this.__store.batch(() => {
|
|
1472
|
+
matches.forEach((match) => {
|
|
1473
|
+
if (!loadedMatchIds[match.id]) {
|
|
1474
|
+
this.__store.setState((s) => ({
|
|
1475
|
+
...s,
|
|
1476
|
+
preloadMatches: [...(s.preloadMatches as any), match],
|
|
1477
|
+
}))
|
|
1478
|
+
}
|
|
1479
|
+
})
|
|
1480
|
+
})
|
|
1481
|
+
|
|
1414
1482
|
matches = await this.loadMatches({
|
|
1415
1483
|
matches,
|
|
1416
1484
|
preload: true,
|
|
@@ -1500,7 +1568,7 @@ export class Router<
|
|
|
1500
1568
|
return {
|
|
1501
1569
|
state: {
|
|
1502
1570
|
dehydratedMatches: this.state.matches.map((d) =>
|
|
1503
|
-
pick(d, ['
|
|
1571
|
+
pick(d, ['id', 'status', 'updatedAt', 'loaderData']),
|
|
1504
1572
|
),
|
|
1505
1573
|
},
|
|
1506
1574
|
}
|
|
@@ -1588,6 +1656,7 @@ export function getInitialRouterState(
|
|
|
1588
1656
|
location,
|
|
1589
1657
|
matches: [],
|
|
1590
1658
|
pendingMatches: [],
|
|
1659
|
+
preloadMatches: [],
|
|
1591
1660
|
lastUpdated: Date.now(),
|
|
1592
1661
|
}
|
|
1593
1662
|
}
|