@tanstack/react-router 0.0.1-beta.205 → 0.0.1-beta.207

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.
@@ -46,6 +46,9 @@ var invariant__default = /*#__PURE__*/_interopDefaultLegacy(invariant);
46
46
 
47
47
  const preloadWarning = 'Error preloading route! ☝️';
48
48
  const routerContext = /*#__PURE__*/React__namespace.createContext(null);
49
+ if (typeof document !== 'undefined') {
50
+ window.__TSR_ROUTER_CONTEXT__ = routerContext;
51
+ }
49
52
  function getInitialRouterState(location) {
50
53
  return {
51
54
  status: 'idle',
@@ -73,6 +76,10 @@ function RouterProvider({
73
76
  const tempLocationKeyRef = React__namespace.useRef(`${Math.round(Math.random() * 10000000)}`);
74
77
  const resetNextScrollRef = React__namespace.useRef(false);
75
78
  const navigateTimeoutRef = React__namespace.useRef(null);
79
+ const latestLoadPromiseRef = React__namespace.useRef(Promise.resolve());
80
+ const checkLatest = promise => {
81
+ return latestLoadPromiseRef.current !== promise ? latestLoadPromiseRef.current : undefined;
82
+ };
76
83
  const parseLocation = utils.useStableCallback(previousLocation => {
77
84
  const parse = ({
78
85
  pathname,
@@ -196,7 +203,6 @@ function RouterProvider({
196
203
  d.child.rank = i;
197
204
  return d.child;
198
205
  }), [routesByPath]);
199
- const latestLoadPromiseRef = React__namespace.useRef(Promise.resolve());
200
206
  const matchRoutes = utils.useStableCallback((pathname, locationSearch, opts) => {
201
207
  let routeParams = {};
202
208
  let foundRoute = flatRoutes.find(route => {
@@ -329,7 +335,7 @@ function RouterProvider({
329
335
  });
330
336
  const buildLocation = utils.useStableCallback((opts = {}) => {
331
337
  const build = (dest = {}, matches) => {
332
- const from = state.location;
338
+ const from = latestLocationRef.current;
333
339
  const fromPathname = dest.from ?? from.pathname;
334
340
  let pathname = resolvePathWithBase(fromPathname, `${dest.to ?? ''}`);
335
341
  const fromMatches = matchRoutes(fromPathname, from.search);
@@ -422,7 +428,7 @@ function RouterProvider({
422
428
  });
423
429
  const commitLocation = utils.useStableCallback(async next => {
424
430
  if (navigateTimeoutRef.current) clearTimeout(navigateTimeoutRef.current);
425
- const isSameUrl = state.location.href === next.href;
431
+ const isSameUrl = latestLocationRef.current.href === next.href;
426
432
 
427
433
  // If the next urls are the same and we're not replacing,
428
434
  // do nothing
@@ -495,9 +501,11 @@ function RouterProvider({
495
501
  });
496
502
  });
497
503
  const loadMatches = utils.useStableCallback(async ({
504
+ checkLatest,
498
505
  matches,
499
506
  preload
500
507
  }) => {
508
+ let latestPromise;
501
509
  let firstBadMatchIndex;
502
510
 
503
511
  // Check each match middleware to see if the route can be accessed
@@ -540,7 +548,7 @@ function RouterProvider({
540
548
  params: match.params,
541
549
  preload: !!preload,
542
550
  meta: parentMeta,
543
- location: state.location
551
+ location: state.location // TODO: This might need to be latestLocationRef.current...?
544
552
  })) ?? {};
545
553
  const meta = {
546
554
  ...parentMeta,
@@ -558,7 +566,7 @@ function RouterProvider({
558
566
  } catch (err) {
559
567
  if (redirects.isRedirect(err)) {
560
568
  if (!preload) navigate(err);
561
- return;
569
+ return matches;
562
570
  }
563
571
  throw err;
564
572
  }
@@ -571,11 +579,6 @@ function RouterProvider({
571
579
  if (match.isFetching) {
572
580
  return getRouteMatch(state, match.id)?.loadPromise;
573
581
  }
574
- const fetchedAt = Date.now();
575
- const checkLatest = () => {
576
- const latest = getRouteMatch(state, match.id);
577
- return latest && latest.fetchedAt !== fetchedAt ? latest.loadPromise : undefined;
578
- };
579
582
  const handleIfRedirect = err => {
580
583
  if (redirects.isRedirect(err)) {
581
584
  if (!preload) {
@@ -586,7 +589,6 @@ function RouterProvider({
586
589
  return false;
587
590
  };
588
591
  const load = async () => {
589
- let latestPromise;
590
592
  try {
591
593
  const componentsPromise = Promise.all(router.componentTypes.map(async type => {
592
594
  const component = route.options[type];
@@ -628,12 +630,18 @@ function RouterProvider({
628
630
  updatedAt: Date.now()
629
631
  };
630
632
  }
633
+ if (!preload) {
634
+ setState(s => ({
635
+ ...s,
636
+ matches: s.matches.map(d => d.id === match.id ? match : d)
637
+ }));
638
+ }
631
639
  };
632
640
  let loadPromise;
633
641
  matches[index] = match = {
634
642
  ...match,
635
643
  isFetching: true,
636
- fetchedAt,
644
+ fetchedAt: Date.now(),
637
645
  invalid: false
638
646
  };
639
647
  loadPromise = load();
@@ -645,35 +653,32 @@ function RouterProvider({
645
653
  })());
646
654
  });
647
655
  await Promise.all(matchPromises);
656
+ return matches;
648
657
  });
649
- const load = utils.useStableCallback(async opts => {
658
+ const load = utils.useStableCallback(async () => {
650
659
  const promise = new Promise(async (resolve, reject) => {
660
+ const next = latestLocationRef.current;
651
661
  const prevLocation = state.resolvedLocation;
652
- const pathDidChange = !!(opts?.next && prevLocation.href !== opts.next.href);
662
+ const pathDidChange = !!(next && prevLocation.href !== next.href);
653
663
  let latestPromise;
654
- const checkLatest = () => {
655
- return latestLoadPromiseRef.current !== promise ? latestLoadPromiseRef.current : undefined;
656
- };
657
664
 
658
665
  // Cancel any pending matches
659
666
  cancelMatches(state);
660
667
  router$1.emit({
661
668
  type: 'onBeforeLoad',
662
669
  from: prevLocation,
663
- to: opts?.next ?? state.location,
670
+ to: next ?? state.location,
664
671
  pathChanged: pathDidChange
665
672
  });
666
- if (opts?.next) {
667
- // Ingest the new location
668
- setState(s => ({
669
- ...s,
670
- location: opts.next
671
- }));
672
- }
673
+
674
+ // Ingest the new location
675
+ setState(s => ({
676
+ ...s,
677
+ location: next
678
+ }));
673
679
 
674
680
  // Match the routes
675
- const matches = matchRoutes(state.location.pathname, state.location.search, {
676
- throwOnError: opts?.throwOnError,
681
+ let matches = matchRoutes(next.pathname, next.search, {
677
682
  debug: true
678
683
  });
679
684
  setState(s => ({
@@ -682,10 +687,11 @@ function RouterProvider({
682
687
  matches
683
688
  }));
684
689
  try {
685
- // Load the matches
686
690
  try {
691
+ // Load the matches
687
692
  await loadMatches({
688
- matches
693
+ matches,
694
+ checkLatest: () => checkLatest(promise)
689
695
  });
690
696
  } catch (err) {
691
697
  // swallow this error, since we'll display the
@@ -693,7 +699,7 @@ function RouterProvider({
693
699
  }
694
700
 
695
701
  // Only apply the latest transition
696
- if (latestPromise = checkLatest()) {
702
+ if (latestPromise = checkLatest(promise)) {
697
703
  return latestPromise;
698
704
  }
699
705
 
@@ -730,13 +736,13 @@ function RouterProvider({
730
736
  router$1.emit({
731
737
  type: 'onLoad',
732
738
  from: prevLocation,
733
- to: state.location,
739
+ to: next,
734
740
  pathChanged: pathDidChange
735
741
  });
736
742
  resolve();
737
743
  } catch (err) {
738
744
  // Only apply the latest transition
739
- if (latestPromise = checkLatest()) {
745
+ if (latestPromise = checkLatest(promise)) {
740
746
  return latestPromise;
741
747
  }
742
748
  reject(err);
@@ -745,13 +751,6 @@ function RouterProvider({
745
751
  latestLoadPromiseRef.current = promise;
746
752
  return latestLoadPromiseRef.current;
747
753
  });
748
- const safeLoad = React__namespace.useCallback(async () => {
749
- try {
750
- return load();
751
- } catch (err) {
752
- // Don't do anything
753
- }
754
- }, []);
755
754
  const preloadRoute = utils.useStableCallback(async (navigateOpts = state.location) => {
756
755
  let next = buildLocation(navigateOpts);
757
756
  let matches = matchRoutes(next.pathname, next.search, {
@@ -759,7 +758,8 @@ function RouterProvider({
759
758
  });
760
759
  await loadMatches({
761
760
  matches,
762
- preload: true
761
+ preload: true,
762
+ checkLatest: () => undefined
763
763
  });
764
764
  return [utils.last(matches), matches];
765
765
  });
@@ -793,13 +793,13 @@ function RouterProvider({
793
793
  const preloadDelay = userPreloadDelay ?? options.defaultPreloadDelay ?? 0;
794
794
 
795
795
  // Compare path/hash for matches
796
- const currentPathSplit = state.location.pathname.split('/');
796
+ const currentPathSplit = latestLocationRef.current.pathname.split('/');
797
797
  const nextPathSplit = next.pathname.split('/');
798
798
  const pathIsFuzzyEqual = nextPathSplit.every((d, i) => d === currentPathSplit[i]);
799
799
  // Combine the matches based on user options
800
- const pathTest = activeOptions?.exact ? state.location.pathname === next.pathname : pathIsFuzzyEqual;
801
- const hashTest = activeOptions?.includeHash ? state.location.hash === next.hash : true;
802
- const searchTest = activeOptions?.includeSearch ?? true ? utils.partialDeepEqual(state.location.search, next.search) : true;
800
+ const pathTest = activeOptions?.exact ? latestLocationRef.current.pathname === next.pathname : pathIsFuzzyEqual;
801
+ const hashTest = activeOptions?.includeHash ? latestLocationRef.current.hash === next.hash : true;
802
+ const searchTest = activeOptions?.includeSearch ?? true ? utils.partialDeepEqual(latestLocationRef.current.search, next.search) : true;
803
803
 
804
804
  // The final "active" test
805
805
  const isActive = pathTest && hashTest && searchTest;
@@ -867,13 +867,18 @@ function RouterProvider({
867
867
  disabled
868
868
  };
869
869
  });
870
+ const latestLocationRef = React__namespace.useRef(state.location);
870
871
  React__namespace.useLayoutEffect(() => {
871
872
  const unsub = history$1.subscribe(() => {
873
+ latestLocationRef.current = parseLocation(latestLocationRef.current);
872
874
  React__namespace.startTransition(() => {
873
- setState(s => ({
874
- ...s,
875
- location: parseLocation(state.location)
876
- }));
875
+ if (state.location !== latestLocationRef.current) {
876
+ try {
877
+ load();
878
+ } catch (err) {
879
+ console.error(err);
880
+ }
881
+ }
877
882
  });
878
883
  });
879
884
  const nextLocation = buildLocation({
@@ -895,13 +900,12 @@ function RouterProvider({
895
900
  const initialLoad = React__namespace.useRef(true);
896
901
  if (initialLoad.current) {
897
902
  initialLoad.current = false;
898
- safeLoad();
899
- }
900
- React__namespace.useLayoutEffect(() => {
901
- if (state.resolvedLocation !== state.location) {
902
- safeLoad();
903
+ try {
904
+ load();
905
+ } catch (err) {
906
+ console.error(err);
903
907
  }
904
- }, [state.location]);
908
+ }
905
909
  React__namespace.useMemo(() => [...state.matches, ...state.pendingMatches].some(d => d.isFetching), [state.matches, state.pendingMatches]);
906
910
  const matchRoute = utils.useStableCallback((state, location, opts) => {
907
911
  location = {
@@ -912,7 +916,7 @@ function RouterProvider({
912
916
  if (opts?.pending && state.status !== 'pending') {
913
917
  return false;
914
918
  }
915
- const baseLocation = opts?.pending ? state.location : state.resolvedLocation;
919
+ const baseLocation = opts?.pending ? latestLocationRef.current : state.resolvedLocation;
916
920
  if (!baseLocation) {
917
921
  return false;
918
922
  }