@tanstack/react-router 0.0.1-beta.280 → 0.0.1-beta.281

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/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.280",
4
+ "version": "0.0.1-beta.281",
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.280"
47
+ "@tanstack/history": "0.0.1-beta.281"
48
48
  },
49
49
  "scripts": {
50
50
  "build": "rollup --config rollup.config.js"
package/src/Matches.tsx CHANGED
@@ -43,6 +43,7 @@ export interface RouteMatch<
43
43
  abortController: AbortController
44
44
  cause: 'preload' | 'enter' | 'stay'
45
45
  loaderDeps: RouteById<TRouteTree, TRouteId>['types']['loaderDeps']
46
+ invalid: boolean
46
47
  }
47
48
 
48
49
  export type AnyRouteMatch = RouteMatch<any, any>
package/src/route.ts CHANGED
@@ -99,6 +99,16 @@ export type BaseRouteOptions<
99
99
  > = RoutePathOptions<TCustomId, TPath> & {
100
100
  getParentRoute: () => TParentRoute
101
101
  validateSearch?: SearchSchemaValidator<TSearchSchema>
102
+ shouldReload?:
103
+ | boolean
104
+ | ((
105
+ match: LoaderFnContext<
106
+ TAllParams,
107
+ TFullSearchSchema,
108
+ TAllContext,
109
+ TRouteContext
110
+ >,
111
+ ) => any)
102
112
  } & (keyof PickRequired<RouteContext> extends never
103
113
  ? // This async function is called before a route is loaded.
104
114
  // If an error is thrown here, the route's loader will not be called.
package/src/router.ts CHANGED
@@ -668,6 +668,7 @@ export class Router<
668
668
  fetchCount: 0,
669
669
  cause,
670
670
  loaderDeps,
671
+ invalid: false,
671
672
  }
672
673
 
673
674
  // Regardless of whether we're reusing an existing match or creating
@@ -974,12 +975,10 @@ export class Router<
974
975
  checkLatest,
975
976
  matches,
976
977
  preload,
977
- invalidate,
978
978
  }: {
979
979
  checkLatest: () => Promise<void> | undefined
980
980
  matches: AnyRouteMatch[]
981
981
  preload?: boolean
982
- invalidate?: boolean
983
982
  }): Promise<RouteMatch[]> => {
984
983
  let latestPromise
985
984
  let firstBadMatchIndex: number | undefined
@@ -1136,22 +1135,25 @@ export class Router<
1136
1135
  (route.options.pendingComponent ??
1137
1136
  this.options.defaultPendingComponent)
1138
1137
 
1138
+ const loaderContext: LoaderFnContext = {
1139
+ params: match.params,
1140
+ deps: match.loaderDeps,
1141
+ preload: !!preload,
1142
+ parentMatchPromise,
1143
+ abortController: match.abortController,
1144
+ context: match.context,
1145
+ location: this.state.location,
1146
+ navigate: (opts) =>
1147
+ this.navigate({ ...opts, from: match.pathname } as any),
1148
+ cause: preload ? 'preload' : match.cause,
1149
+ }
1150
+
1139
1151
  const fetch = async () => {
1140
1152
  if (match.isFetching) {
1141
1153
  loadPromise = getRouteMatch(this.state, match.id)?.loadPromise
1142
1154
  } else {
1143
- const loaderContext: LoaderFnContext = {
1144
- params: match.params,
1145
- deps: match.loaderDeps,
1146
- preload: !!preload,
1147
- parentMatchPromise,
1148
- abortController: match.abortController,
1149
- context: match.context,
1150
- location: this.state.location,
1151
- navigate: (opts) =>
1152
- this.navigate({ ...opts, from: match.pathname } as any),
1153
- cause: preload ? 'preload' : match.cause,
1154
- }
1155
+ // If the user doesn't want the route to reload, just
1156
+ // resolve with the existing loader data
1155
1157
 
1156
1158
  if (match.fetchCount && match.status === 'success') {
1157
1159
  resolve()
@@ -1243,14 +1245,19 @@ export class Router<
1243
1245
  30_000 // 30 seconds for preloads by default
1244
1246
  : route.options.staleTime ?? this.options.defaultStaleTime ?? 0
1245
1247
 
1246
- if (match.status === 'success') {
1247
- // Background Fetching, no need to wait
1248
- if (age > staleAge) {
1249
- fetch()
1250
- }
1251
- } else {
1252
- // Critical Fetching, we need to await
1248
+ // Default to reloading the route all the time
1249
+ let shouldReload
1250
+
1251
+ const shouldReloadOption = route.options.shouldReload
1253
1252
 
1253
+ // Allow shouldReload to get the last say,
1254
+ // if provided.
1255
+ shouldReload =
1256
+ typeof shouldReloadOption === 'function'
1257
+ ? shouldReloadOption(loaderContext)
1258
+ : shouldReloadOption
1259
+
1260
+ if (match.status !== 'success') {
1254
1261
  // If we need to potentially show the pending component,
1255
1262
  // start a timer to show it after the pendingMs
1256
1263
  if (shouldPending) {
@@ -1268,7 +1275,11 @@ export class Router<
1268
1275
  })
1269
1276
  }
1270
1277
 
1278
+ // Critical Fetching, we need to await
1271
1279
  await fetch()
1280
+ } else if (match.invalid || (shouldReload ?? age > staleAge)) {
1281
+ // Background Fetching, no need to wait
1282
+ fetch()
1272
1283
  }
1273
1284
 
1274
1285
  resolve()
@@ -1280,12 +1291,23 @@ export class Router<
1280
1291
  return matches
1281
1292
  }
1282
1293
 
1283
- invalidate = () =>
1284
- this.load({
1285
- invalidate: true,
1294
+ invalidate = () => {
1295
+ const invalidate = (d: any) => ({
1296
+ ...d,
1297
+ invalid: true,
1286
1298
  })
1287
1299
 
1288
- load = async (opts?: { invalidate?: boolean }): Promise<void> => {
1300
+ this.__store.setState((s) => ({
1301
+ ...s,
1302
+ matches: s.matches.map(invalidate),
1303
+ cachedMatches: s.cachedMatches.map(invalidate),
1304
+ pendingMatches: s.pendingMatches?.map(invalidate),
1305
+ }))
1306
+
1307
+ this.load()
1308
+ }
1309
+
1310
+ load = async (): Promise<void> => {
1289
1311
  const promise = new Promise<void>(async (resolve, reject) => {
1290
1312
  const next = this.latestLocation
1291
1313
  const prevLocation = this.state.resolvedLocation
@@ -1348,7 +1370,6 @@ export class Router<
1348
1370
  await this.loadMatches({
1349
1371
  matches: pendingMatches,
1350
1372
  checkLatest: () => this.checkLatest(promise),
1351
- invalidate: opts?.invalidate,
1352
1373
  })
1353
1374
  } catch (err) {
1354
1375
  // swallow this error, since we'll display the