@tanstack/react-router 0.0.1-beta.279 → 0.0.1-beta.280
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 +1 -2
- package/build/cjs/RouterProvider.js.map +1 -1
- package/build/cjs/link.js +1 -1
- package/build/cjs/link.js.map +1 -1
- package/build/cjs/route.js.map +1 -1
- package/build/cjs/router.js +54 -91
- package/build/cjs/router.js.map +1 -1
- package/build/esm/index.js +56 -94
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +1 -1
- package/build/stats-react.json +355 -355
- package/build/types/Matches.d.ts +0 -1
- package/build/types/fileRoute.d.ts +4 -0
- package/build/types/route.d.ts +4 -1
- package/build/types/router.d.ts +5 -3
- package/build/umd/index.development.js +56 -94
- 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 +0 -1
- package/src/RouterProvider.tsx +1 -2
- package/src/link.tsx +1 -1
- package/src/route.ts +4 -10
- package/src/router.ts +86 -123
package/build/cjs/router.js
CHANGED
|
@@ -31,7 +31,6 @@ class Router {
|
|
|
31
31
|
navigateTimeout = null;
|
|
32
32
|
latestLoadPromise = Promise.resolve();
|
|
33
33
|
subscribers = new Set();
|
|
34
|
-
pendingMatches = [];
|
|
35
34
|
injectedHtml = [];
|
|
36
35
|
|
|
37
36
|
// Must build in constructor
|
|
@@ -355,7 +354,6 @@ class Router {
|
|
|
355
354
|
routeContext: undefined,
|
|
356
355
|
context: undefined,
|
|
357
356
|
abortController: new AbortController(),
|
|
358
|
-
shouldReloadDeps: undefined,
|
|
359
357
|
fetchCount: 0,
|
|
360
358
|
cause,
|
|
361
359
|
loaderDeps
|
|
@@ -567,9 +565,10 @@ class Router {
|
|
|
567
565
|
let latestPromise;
|
|
568
566
|
let firstBadMatchIndex;
|
|
569
567
|
const updateMatch = match => {
|
|
570
|
-
// const isPreload = this.state.
|
|
568
|
+
// const isPreload = this.state.cachedMatches.find((d) => d.id === match.id)
|
|
571
569
|
const isPending = this.state.pendingMatches?.find(d => d.id === match.id);
|
|
572
|
-
const
|
|
570
|
+
const isMatched = this.state.matches.find(d => d.id === match.id);
|
|
571
|
+
const matchesKey = isPending ? 'pendingMatches' : isMatched ? 'matches' : 'cachedMatches';
|
|
573
572
|
this.__store.setState(s => ({
|
|
574
573
|
...s,
|
|
575
574
|
[matchesKey]: s[matchesKey]?.map(d => d.id === match.id ? match : d)
|
|
@@ -694,65 +693,24 @@ class Router {
|
|
|
694
693
|
}),
|
|
695
694
|
cause: preload ? 'preload' : match.cause
|
|
696
695
|
};
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
let shouldLoad = true;
|
|
700
|
-
const shouldReloadFn = route.options.shouldReload;
|
|
701
|
-
let shouldReloadDeps = typeof shouldReloadFn === 'function' ? shouldReloadFn(loaderContext) : !!(shouldReloadFn ?? true);
|
|
702
|
-
const compareDeps = () => {
|
|
703
|
-
if (typeof shouldReloadDeps === 'object') {
|
|
704
|
-
// compare the deps to see if they've changed
|
|
705
|
-
shouldLoad = !utils.deepEqual(shouldReloadDeps, match.shouldReloadDeps);
|
|
706
|
-
} else {
|
|
707
|
-
shouldLoad = !!shouldReloadDeps;
|
|
708
|
-
}
|
|
709
|
-
};
|
|
710
|
-
|
|
711
|
-
// If it's the first preload, or the route is entering, or we're
|
|
712
|
-
// invalidating, we definitely need to load the route
|
|
713
|
-
if (invalidate) ; else if (preload) {
|
|
714
|
-
if (!match.fetchCount) ; else {
|
|
715
|
-
compareDeps();
|
|
716
|
-
}
|
|
717
|
-
} else if (match.cause === 'enter') {
|
|
718
|
-
if (!match.fetchCount) ; else {
|
|
719
|
-
compareDeps();
|
|
720
|
-
}
|
|
721
|
-
} else {
|
|
722
|
-
compareDeps();
|
|
723
|
-
}
|
|
724
|
-
if (typeof shouldReloadDeps === 'object') {
|
|
725
|
-
matches[index] = match = {
|
|
726
|
-
...match,
|
|
727
|
-
shouldReloadDeps
|
|
728
|
-
};
|
|
696
|
+
if (match.fetchCount && match.status === 'success') {
|
|
697
|
+
resolve();
|
|
729
698
|
}
|
|
730
699
|
|
|
731
|
-
//
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
|
|
700
|
+
// Otherwise, load the route
|
|
701
|
+
matches[index] = match = {
|
|
702
|
+
...match,
|
|
703
|
+
isFetching: true,
|
|
704
|
+
fetchCount: match.fetchCount + 1
|
|
705
|
+
};
|
|
706
|
+
const componentsPromise = Promise.all(componentTypes.map(async type => {
|
|
707
|
+
const component = route.options[type];
|
|
708
|
+
if (component?.preload) {
|
|
709
|
+
await component.preload();
|
|
739
710
|
}
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
...match,
|
|
744
|
-
isFetching: true,
|
|
745
|
-
fetchCount: match.fetchCount + 1
|
|
746
|
-
};
|
|
747
|
-
const componentsPromise = Promise.all(componentTypes.map(async type => {
|
|
748
|
-
const component = route.options[type];
|
|
749
|
-
if (component?.preload) {
|
|
750
|
-
await component.preload();
|
|
751
|
-
}
|
|
752
|
-
}));
|
|
753
|
-
const loaderPromise = route.options.loader?.(loaderContext);
|
|
754
|
-
loadPromise = Promise.all([componentsPromise, loaderPromise]).then(d => d[1]);
|
|
755
|
-
}
|
|
711
|
+
}));
|
|
712
|
+
const loaderPromise = route.options.loader?.(loaderContext);
|
|
713
|
+
loadPromise = Promise.all([componentsPromise, loaderPromise]).then(d => d[1]);
|
|
756
714
|
}
|
|
757
715
|
matches[index] = match = {
|
|
758
716
|
...match,
|
|
@@ -791,24 +749,23 @@ class Router {
|
|
|
791
749
|
...match,
|
|
792
750
|
error,
|
|
793
751
|
status: 'error',
|
|
794
|
-
isFetching: false
|
|
795
|
-
updatedAt: Date.now()
|
|
752
|
+
isFetching: false
|
|
796
753
|
};
|
|
797
|
-
} finally {
|
|
798
|
-
// If we showed the pending component, that means
|
|
799
|
-
// we already moved the pendingMatches to the matches
|
|
800
|
-
// state, so we need to update that specific match
|
|
801
|
-
if (didShowPending && pendingMinMs && match.showPending) {
|
|
802
|
-
updateMatch(match);
|
|
803
|
-
}
|
|
804
754
|
}
|
|
805
755
|
updateMatch(match);
|
|
806
756
|
};
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
757
|
+
|
|
758
|
+
// This is where all of the stale-while-revalidate magic happens
|
|
759
|
+
const age = Date.now() - match.updatedAt;
|
|
760
|
+
let staleAge = preload ? route.options.preloadStaleTime ?? this.options.defaultPreloadStaleTime ?? 30_000 // 30 seconds for preloads by default
|
|
761
|
+
: route.options.staleTime ?? this.options.defaultStaleTime ?? 0;
|
|
762
|
+
if (match.status === 'success') {
|
|
763
|
+
// Background Fetching, no need to wait
|
|
764
|
+
if (age > staleAge) {
|
|
765
|
+
fetch();
|
|
766
|
+
}
|
|
810
767
|
} else {
|
|
811
|
-
// Critical Fetching
|
|
768
|
+
// Critical Fetching, we need to await
|
|
812
769
|
|
|
813
770
|
// If we need to potentially show the pending component,
|
|
814
771
|
// start a timer to show it after the pendingMs
|
|
@@ -827,9 +784,6 @@ class Router {
|
|
|
827
784
|
await fetch();
|
|
828
785
|
}
|
|
829
786
|
resolve();
|
|
830
|
-
// No Fetching
|
|
831
|
-
|
|
832
|
-
resolve();
|
|
833
787
|
}));
|
|
834
788
|
});
|
|
835
789
|
await Promise.all(matchPromises);
|
|
@@ -856,12 +810,16 @@ class Router {
|
|
|
856
810
|
let pendingMatches;
|
|
857
811
|
const previousMatches = this.state.matches;
|
|
858
812
|
this.__store.batch(() => {
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
813
|
+
// This is where all of the garbage collection magic happens
|
|
814
|
+
this.__store.setState(s => {
|
|
815
|
+
return {
|
|
816
|
+
...s,
|
|
817
|
+
cachedMatches: s.cachedMatches.filter(d => {
|
|
818
|
+
const route = this.looseRoutesById[d.routeId];
|
|
819
|
+
return d.status !== 'error' && Date.now() - d.updatedAt < (route.options.gcTime ?? this.options.defaultGcTime ?? 5 * 60 * 1000);
|
|
820
|
+
})
|
|
821
|
+
};
|
|
822
|
+
});
|
|
865
823
|
|
|
866
824
|
// Match the routes
|
|
867
825
|
pendingMatches = this.matchRoutes(next.pathname, next.search, {
|
|
@@ -869,12 +827,13 @@ class Router {
|
|
|
869
827
|
});
|
|
870
828
|
|
|
871
829
|
// Ingest the new matches
|
|
830
|
+
// If a cached moved to pendingMatches, remove it from cachedMatches
|
|
872
831
|
this.__store.setState(s => ({
|
|
873
832
|
...s,
|
|
874
833
|
isLoading: true,
|
|
875
834
|
location: next,
|
|
876
835
|
pendingMatches,
|
|
877
|
-
|
|
836
|
+
cachedMatches: s.cachedMatches.filter(d => {
|
|
878
837
|
return !pendingMatches.find(e => e.id === d.id);
|
|
879
838
|
})
|
|
880
839
|
}));
|
|
@@ -896,19 +855,23 @@ class Router {
|
|
|
896
855
|
if (latestPromise = this.checkLatest(promise)) {
|
|
897
856
|
return latestPromise;
|
|
898
857
|
}
|
|
899
|
-
const
|
|
900
|
-
const
|
|
901
|
-
const
|
|
858
|
+
const exitingMatches = previousMatches.filter(match => !pendingMatches.find(d => d.id === match.id));
|
|
859
|
+
const enteringMatches = pendingMatches.filter(match => !previousMatches.find(d => d.id === match.id));
|
|
860
|
+
const stayingMatches = previousMatches.filter(match => pendingMatches.find(d => d.id === match.id));
|
|
861
|
+
|
|
862
|
+
// Commit the pending matches. If a previous match was
|
|
863
|
+
// removed, place it in the cachedMatches
|
|
902
864
|
this.__store.setState(s => ({
|
|
903
865
|
...s,
|
|
904
866
|
isLoading: false,
|
|
905
867
|
matches: pendingMatches,
|
|
906
|
-
pendingMatches: undefined
|
|
868
|
+
pendingMatches: undefined,
|
|
869
|
+
cachedMatches: [...s.cachedMatches, ...exitingMatches.filter(d => d.status !== 'error')]
|
|
907
870
|
}))
|
|
908
871
|
|
|
909
872
|
//
|
|
910
873
|
;
|
|
911
|
-
[[
|
|
874
|
+
[[exitingMatches, 'onLeave'], [enteringMatches, 'onEnter'], [stayingMatches, 'onStay']].forEach(([matches, hook]) => {
|
|
912
875
|
matches.forEach(match => {
|
|
913
876
|
this.looseRoutesById[match.routeId].options[hook]?.(match);
|
|
914
877
|
});
|
|
@@ -936,13 +899,13 @@ class Router {
|
|
|
936
899
|
let matches = this.matchRoutes(next.pathname, next.search, {
|
|
937
900
|
throwOnError: true
|
|
938
901
|
});
|
|
939
|
-
const loadedMatchIds = Object.fromEntries([...this.state.matches, ...(this.state.pendingMatches ?? []), ...this.state.
|
|
902
|
+
const loadedMatchIds = Object.fromEntries([...this.state.matches, ...(this.state.pendingMatches ?? []), ...this.state.cachedMatches]?.map(d => [d.id, true]));
|
|
940
903
|
this.__store.batch(() => {
|
|
941
904
|
matches.forEach(match => {
|
|
942
905
|
if (!loadedMatchIds[match.id]) {
|
|
943
906
|
this.__store.setState(s => ({
|
|
944
907
|
...s,
|
|
945
|
-
|
|
908
|
+
cachedMatches: [...s.cachedMatches, match]
|
|
946
909
|
}));
|
|
947
910
|
}
|
|
948
911
|
});
|
|
@@ -1072,7 +1035,7 @@ function getInitialRouterState(location) {
|
|
|
1072
1035
|
location,
|
|
1073
1036
|
matches: [],
|
|
1074
1037
|
pendingMatches: [],
|
|
1075
|
-
|
|
1038
|
+
cachedMatches: [],
|
|
1076
1039
|
lastUpdated: Date.now()
|
|
1077
1040
|
};
|
|
1078
1041
|
}
|