@tanstack/router-core 1.120.4 → 1.120.5

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.120.4",
3
+ "version": "1.120.5",
4
4
  "description": "Modern and scalable routing for React applications",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
package/src/route.ts CHANGED
@@ -960,7 +960,7 @@ type AssetFnContextOptions<
960
960
  TLoaderDeps
961
961
  >
962
962
  params: ResolveAllParamsFromParent<TParentRoute, TParams>
963
- loaderData: ResolveLoaderData<TLoaderFn>
963
+ loaderData?: ResolveLoaderData<TLoaderFn>
964
964
  }
965
965
 
966
966
  export interface DefaultUpdatableRouteOptionsExtensions {
@@ -1070,9 +1070,20 @@ export interface UpdatableRouteOptions<
1070
1070
  TLoaderDeps
1071
1071
  >,
1072
1072
  ) => void
1073
- headers?: (ctx: {
1074
- loaderData: ResolveLoaderData<TLoaderFn>
1075
- }) => Record<string, string>
1073
+ headers?: (
1074
+ ctx: AssetFnContextOptions<
1075
+ TRouteId,
1076
+ TFullPath,
1077
+ TParentRoute,
1078
+ TParams,
1079
+ TSearchValidator,
1080
+ TLoaderFn,
1081
+ TRouterContext,
1082
+ TRouteContextFn,
1083
+ TBeforeLoadFn,
1084
+ TLoaderDeps
1085
+ >,
1086
+ ) => Record<string, string>
1076
1087
  head?: (
1077
1088
  ctx: AssetFnContextOptions<
1078
1089
  TRouteId,
package/src/router.ts CHANGED
@@ -1447,26 +1447,6 @@ export class RouterCore<
1447
1447
  ...match.__beforeLoadContext,
1448
1448
  }
1449
1449
  }
1450
-
1451
- // If it's already a success, update headers and head content
1452
- // These may get updated again if the match is refreshed
1453
- // due to being stale
1454
- if (match.status === 'success') {
1455
- match.headers = route.options.headers?.({
1456
- loaderData: match.loaderData,
1457
- })
1458
- const assetContext = {
1459
- matches,
1460
- match,
1461
- params: match.params,
1462
- loaderData: match.loaderData,
1463
- }
1464
- const headFnContent = route.options.head?.(assetContext)
1465
- match.links = headFnContent?.links
1466
- match.headScripts = headFnContent?.scripts
1467
- match.meta = headFnContent?.meta
1468
- match.scripts = route.options.scripts?.(assetContext)
1469
- }
1470
1450
  })
1471
1451
 
1472
1452
  return matches
@@ -2609,6 +2589,35 @@ export class RouterCore<
2609
2589
  !this.state.matches.find((d) => d.id === matchId),
2610
2590
  }))
2611
2591
 
2592
+ const executeHead = () => {
2593
+ const match = this.getMatch(matchId)
2594
+ // in case of a redirecting match during preload, the match does not exist
2595
+ if (!match) {
2596
+ return
2597
+ }
2598
+ const assetContext = {
2599
+ matches,
2600
+ match,
2601
+ params: match.params,
2602
+ loaderData: match.loaderData,
2603
+ }
2604
+ const headFnContent = route.options.head?.(assetContext)
2605
+ const meta = headFnContent?.meta
2606
+ const links = headFnContent?.links
2607
+ const headScripts = headFnContent?.scripts
2608
+
2609
+ const scripts = route.options.scripts?.(assetContext)
2610
+ const headers = route.options.headers?.(assetContext)
2611
+ updateMatch(matchId, (prev) => ({
2612
+ ...prev,
2613
+ meta,
2614
+ links,
2615
+ headScripts,
2616
+ headers,
2617
+ scripts,
2618
+ }))
2619
+ }
2620
+
2612
2621
  const runLoader = async () => {
2613
2622
  try {
2614
2623
  // If the Matches component rendered
@@ -2649,40 +2658,21 @@ export class RouterCore<
2649
2658
 
2650
2659
  await potentialPendingMinPromise()
2651
2660
 
2652
- const assetContext = {
2653
- matches,
2654
- match: this.getMatch(matchId)!,
2655
- params: this.getMatch(matchId)!.params,
2656
- loaderData,
2657
- }
2658
- const headFnContent =
2659
- route.options.head?.(assetContext)
2660
- const meta = headFnContent?.meta
2661
- const links = headFnContent?.links
2662
- const headScripts = headFnContent?.scripts
2663
-
2664
- const scripts = route.options.scripts?.(assetContext)
2665
- const headers = route.options.headers?.({
2666
- loaderData,
2667
- })
2668
-
2669
2661
  // Last but not least, wait for the the components
2670
2662
  // to be preloaded before we resolve the match
2671
2663
  await route._componentsPromise
2672
2664
 
2673
- updateMatch(matchId, (prev) => ({
2674
- ...prev,
2675
- error: undefined,
2676
- status: 'success',
2677
- isFetching: false,
2678
- updatedAt: Date.now(),
2679
- loaderData,
2680
- meta,
2681
- links,
2682
- headScripts,
2683
- headers,
2684
- scripts,
2685
- }))
2665
+ batch(() => {
2666
+ updateMatch(matchId, (prev) => ({
2667
+ ...prev,
2668
+ error: undefined,
2669
+ status: 'success',
2670
+ isFetching: false,
2671
+ updatedAt: Date.now(),
2672
+ loaderData,
2673
+ }))
2674
+ executeHead()
2675
+ })
2686
2676
  } catch (e) {
2687
2677
  let error = e
2688
2678
 
@@ -2700,12 +2690,15 @@ export class RouterCore<
2700
2690
  )
2701
2691
  }
2702
2692
 
2703
- updateMatch(matchId, (prev) => ({
2704
- ...prev,
2705
- error,
2706
- status: 'error',
2707
- isFetching: false,
2708
- }))
2693
+ batch(() => {
2694
+ updateMatch(matchId, (prev) => ({
2695
+ ...prev,
2696
+ error,
2697
+ status: 'error',
2698
+ isFetching: false,
2699
+ }))
2700
+ executeHead()
2701
+ })
2709
2702
  }
2710
2703
 
2711
2704
  this.serverSsr?.onMatchSettled({
@@ -2713,10 +2706,13 @@ export class RouterCore<
2713
2706
  match: this.getMatch(matchId)!,
2714
2707
  })
2715
2708
  } catch (err) {
2716
- updateMatch(matchId, (prev) => ({
2717
- ...prev,
2718
- loaderPromise: undefined,
2719
- }))
2709
+ batch(() => {
2710
+ updateMatch(matchId, (prev) => ({
2711
+ ...prev,
2712
+ loaderPromise: undefined,
2713
+ }))
2714
+ executeHead()
2715
+ })
2720
2716
  handleRedirectAndNotFound(this.getMatch(matchId)!, err)
2721
2717
  }
2722
2718
  }
@@ -2752,6 +2748,11 @@ export class RouterCore<
2752
2748
  (loaderShouldRunAsync && sync)
2753
2749
  ) {
2754
2750
  await runLoader()
2751
+ } else {
2752
+ // if the loader did not run, still update head.
2753
+ // reason: parent's beforeLoad may have changed the route context
2754
+ // and only now do we know the route context (and that the loader would not run)
2755
+ executeHead()
2755
2756
  }
2756
2757
  }
2757
2758
  if (!loaderIsRunningAsync) {