@tanstack/router-core 1.125.0 → 1.125.3

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,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/router-core",
3
- "version": "1.125.0",
3
+ "version": "1.125.3",
4
4
  "description": "Modern and scalable routing for React applications",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
package/src/path.ts CHANGED
@@ -330,6 +330,21 @@ export function interpolatePath({
330
330
  usedParams._splat = params._splat
331
331
  const segmentPrefix = segment.prefixSegment || ''
332
332
  const segmentSuffix = segment.suffixSegment || ''
333
+
334
+ // Check if _splat parameter is missing
335
+ if (!('_splat' in params)) {
336
+ isMissingParams = true
337
+ // For missing splat parameters, just return the prefix and suffix without the wildcard
338
+ if (leaveWildcards) {
339
+ return `${segmentPrefix}${segment.value}${segmentSuffix}`
340
+ }
341
+ // If there is a prefix or suffix, return them joined, otherwise omit the segment
342
+ if (segmentPrefix || segmentSuffix) {
343
+ return `${segmentPrefix}${segmentSuffix}`
344
+ }
345
+ return undefined
346
+ }
347
+
333
348
  const value = encodeParam('_splat')
334
349
  if (leaveWildcards) {
335
350
  return `${segmentPrefix}${segment.value}${value ?? ''}${segmentSuffix}`
package/src/router.ts CHANGED
@@ -1391,7 +1391,13 @@ export class RouterCore<
1391
1391
  if (!match) return
1392
1392
 
1393
1393
  match.abortController.abort()
1394
- clearTimeout(match.pendingTimeout)
1394
+ this.updateMatch(id, (prev) => {
1395
+ clearTimeout(prev.pendingTimeout)
1396
+ return {
1397
+ ...prev,
1398
+ pendingTimeout: undefined,
1399
+ }
1400
+ })
1395
1401
  }
1396
1402
 
1397
1403
  cancelMatches = () => {
@@ -2312,21 +2318,31 @@ export class RouterCore<
2312
2318
  )
2313
2319
 
2314
2320
  let executeBeforeLoad = true
2315
- if (
2316
- // If we are in the middle of a load, either of these will be present
2317
- // (not to be confused with `loadPromise`, which is always defined)
2318
- existingMatch.beforeLoadPromise ||
2319
- existingMatch.loaderPromise
2320
- ) {
2321
- if (shouldPending) {
2322
- setTimeout(() => {
2321
+ const setupPendingTimeout = () => {
2322
+ if (
2323
+ shouldPending &&
2324
+ this.getMatch(matchId)!.pendingTimeout === undefined
2325
+ ) {
2326
+ const pendingTimeout = setTimeout(() => {
2323
2327
  try {
2324
2328
  // Update the match and prematurely resolve the loadMatches promise so that
2325
2329
  // the pending component can start rendering
2326
2330
  triggerOnReady()
2327
2331
  } catch {}
2328
2332
  }, pendingMs)
2333
+ updateMatch(matchId, (prev) => ({
2334
+ ...prev,
2335
+ pendingTimeout,
2336
+ }))
2329
2337
  }
2338
+ }
2339
+ if (
2340
+ // If we are in the middle of a load, either of these will be present
2341
+ // (not to be confused with `loadPromise`, which is always defined)
2342
+ existingMatch.beforeLoadPromise ||
2343
+ existingMatch.loaderPromise
2344
+ ) {
2345
+ setupPendingTimeout()
2330
2346
 
2331
2347
  // Wait for the beforeLoad to resolve before we continue
2332
2348
  await existingMatch.beforeLoadPromise
@@ -2354,21 +2370,6 @@ export class RouterCore<
2354
2370
  beforeLoadPromise: createControlledPromise<void>(),
2355
2371
  }
2356
2372
  })
2357
- const abortController = new AbortController()
2358
-
2359
- let pendingTimeout: ReturnType<typeof setTimeout>
2360
-
2361
- if (shouldPending) {
2362
- // If we might show a pending component, we need to wait for the
2363
- // pending promise to resolve before we start showing that state
2364
- pendingTimeout = setTimeout(() => {
2365
- try {
2366
- // Update the match and prematurely resolve the loadMatches promise so that
2367
- // the pending component can start rendering
2368
- triggerOnReady()
2369
- } catch {}
2370
- }, pendingMs)
2371
- }
2372
2373
 
2373
2374
  const { paramsError, searchError } = this.getMatch(matchId)!
2374
2375
 
@@ -2380,6 +2381,10 @@ export class RouterCore<
2380
2381
  handleSerialError(index, searchError, 'VALIDATE_SEARCH')
2381
2382
  }
2382
2383
 
2384
+ setupPendingTimeout()
2385
+
2386
+ const abortController = new AbortController()
2387
+
2383
2388
  const parentMatchContext =
2384
2389
  parentMatch?.context ?? this.options.context ?? {}
2385
2390
 
@@ -2388,7 +2393,6 @@ export class RouterCore<
2388
2393
  isFetching: 'beforeLoad',
2389
2394
  fetchCount: prev.fetchCount + 1,
2390
2395
  abortController,
2391
- pendingTimeout,
2392
2396
  context: {
2393
2397
  ...parentMatchContext,
2394
2398
  ...prev.__routeContext,
@@ -2758,16 +2762,22 @@ export class RouterCore<
2758
2762
  loadPromise?.resolve()
2759
2763
  }
2760
2764
 
2761
- updateMatch(matchId, (prev) => ({
2762
- ...prev,
2763
- isFetching: loaderIsRunningAsync ? prev.isFetching : false,
2764
- loaderPromise: loaderIsRunningAsync
2765
- ? prev.loaderPromise
2766
- : undefined,
2767
- invalid: false,
2768
- _dehydrated: undefined,
2769
- _forcePending: undefined,
2770
- }))
2765
+ updateMatch(matchId, (prev) => {
2766
+ clearTimeout(prev.pendingTimeout)
2767
+ return {
2768
+ ...prev,
2769
+ isFetching: loaderIsRunningAsync
2770
+ ? prev.isFetching
2771
+ : false,
2772
+ loaderPromise: loaderIsRunningAsync
2773
+ ? prev.loaderPromise
2774
+ : undefined,
2775
+ invalid: false,
2776
+ pendingTimeout: undefined,
2777
+ _dehydrated: undefined,
2778
+ _forcePending: undefined,
2779
+ }
2780
+ })
2771
2781
  return this.getMatch(matchId)!
2772
2782
  })(),
2773
2783
  )