@tanstack/react-router 0.0.1-beta.273 → 0.0.1-beta.274
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 +9 -6
- package/build/cjs/RouterProvider.js.map +1 -1
- package/build/cjs/index.js +4 -1
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/route.js.map +1 -1
- package/build/cjs/router.js +150 -100
- package/build/cjs/router.js.map +1 -1
- package/build/esm/index.js +157 -103
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +1 -1
- package/build/stats-react.json +353 -353
- package/build/types/Matches.d.ts +2 -2
- package/build/types/RouterProvider.d.ts +1 -1
- package/build/types/route.d.ts +2 -2
- package/build/types/router.d.ts +3 -1
- package/build/umd/index.development.js +159 -106
- 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 +2 -2
- package/src/RouterProvider.tsx +11 -5
- package/src/route.ts +2 -2
- package/src/router.ts +197 -128
package/build/cjs/router.js
CHANGED
|
@@ -353,7 +353,7 @@ class Router {
|
|
|
353
353
|
context: undefined,
|
|
354
354
|
abortController: new AbortController(),
|
|
355
355
|
shouldReloadDeps: undefined,
|
|
356
|
-
|
|
356
|
+
fetchCount: 0,
|
|
357
357
|
cause
|
|
358
358
|
};
|
|
359
359
|
|
|
@@ -562,10 +562,13 @@ class Router {
|
|
|
562
562
|
}) => {
|
|
563
563
|
let latestPromise;
|
|
564
564
|
let firstBadMatchIndex;
|
|
565
|
-
const
|
|
565
|
+
const updateMatch = match => {
|
|
566
|
+
const isPreload = this.state.preloadMatches.find(d => d.id === match.id);
|
|
567
|
+
const isPending = this.state.pendingMatches?.find(d => d.id === match.id);
|
|
568
|
+
const matchesKey = isPreload ? 'preloadMatches' : isPending ? 'pendingMatches' : 'matches';
|
|
566
569
|
this.__store.setState(s => ({
|
|
567
570
|
...s,
|
|
568
|
-
|
|
571
|
+
[matchesKey]: s[matchesKey]?.map(d => d.id === match.id ? match : d)
|
|
569
572
|
}));
|
|
570
573
|
};
|
|
571
574
|
|
|
@@ -618,7 +621,7 @@ class Router {
|
|
|
618
621
|
from: match.pathname
|
|
619
622
|
}),
|
|
620
623
|
buildLocation: this.buildLocation,
|
|
621
|
-
cause: match.cause
|
|
624
|
+
cause: preload ? 'preload' : match.cause
|
|
622
625
|
})) ?? {};
|
|
623
626
|
if (redirects.isRedirect(beforeLoadContext)) {
|
|
624
627
|
throw beforeLoadContext;
|
|
@@ -648,7 +651,7 @@ class Router {
|
|
|
648
651
|
const validResolvedMatches = matches.slice(0, firstBadMatchIndex);
|
|
649
652
|
const matchPromises = [];
|
|
650
653
|
validResolvedMatches.forEach((match, index) => {
|
|
651
|
-
matchPromises.push((async
|
|
654
|
+
matchPromises.push(new Promise(async resolve => {
|
|
652
655
|
const parentMatchPromise = matchPromises[index - 1];
|
|
653
656
|
const route = this.looseRoutesById[match.routeId];
|
|
654
657
|
const handleErrorAndRedirect = err => {
|
|
@@ -663,92 +666,95 @@ class Router {
|
|
|
663
666
|
let loadPromise;
|
|
664
667
|
matches[index] = match = {
|
|
665
668
|
...match,
|
|
666
|
-
fetchedAt: Date.now(),
|
|
667
669
|
showPending: false
|
|
668
670
|
};
|
|
671
|
+
let didShowPending = false;
|
|
669
672
|
const pendingMs = route.options.pendingMs ?? this.options.defaultPendingMs;
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
};
|
|
673
|
+
const pendingMinMs = route.options.pendingMinMs ?? this.options.defaultPendingMinMs;
|
|
674
|
+
const shouldPending = !preload && pendingMs && (route.options.pendingComponent ?? this.options.defaultPendingComponent);
|
|
675
|
+
const fetch = async () => {
|
|
676
|
+
if (match.isFetching) {
|
|
677
|
+
loadPromise = RouterProvider.getRouteMatch(this.state, match.id)?.loadPromise;
|
|
678
|
+
} else {
|
|
679
|
+
const loaderContext = {
|
|
680
|
+
params: match.params,
|
|
681
|
+
search: match.search,
|
|
682
|
+
preload: !!preload,
|
|
683
|
+
parentMatchPromise,
|
|
684
|
+
abortController: match.abortController,
|
|
685
|
+
context: match.context,
|
|
686
|
+
location: this.state.location,
|
|
687
|
+
navigate: opts => this.navigate({
|
|
688
|
+
...opts,
|
|
689
|
+
from: match.pathname
|
|
690
|
+
}),
|
|
691
|
+
cause: preload ? 'preload' : match.cause
|
|
692
|
+
};
|
|
691
693
|
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
694
|
+
// Default to reloading the route all the time
|
|
695
|
+
let shouldLoad = true;
|
|
696
|
+
const shouldReloadFn = route.options.shouldReload;
|
|
697
|
+
let shouldReloadDeps = typeof shouldReloadFn === 'function' ? shouldReloadFn(loaderContext) : !!(shouldReloadFn ?? true);
|
|
698
|
+
const compareDeps = () => {
|
|
699
|
+
if (typeof shouldReloadDeps === 'object') {
|
|
700
|
+
// compare the deps to see if they've changed
|
|
701
|
+
shouldLoad = !utils.deepEqual(shouldReloadDeps, match.shouldReloadDeps);
|
|
702
|
+
} else {
|
|
703
|
+
shouldLoad = !!shouldReloadDeps;
|
|
704
|
+
}
|
|
705
|
+
};
|
|
706
|
+
|
|
707
|
+
// If it's the first preload, or the route is entering, or we're
|
|
708
|
+
// invalidating, we definitely need to load the route
|
|
709
|
+
if (invalidate) ; else if (preload) {
|
|
710
|
+
if (!match.fetchCount) ; else {
|
|
711
|
+
compareDeps();
|
|
712
|
+
}
|
|
713
|
+
} else if (match.cause === 'enter') {
|
|
714
|
+
if (!match.fetchCount) ; else {
|
|
715
|
+
compareDeps();
|
|
716
|
+
}
|
|
702
717
|
} else {
|
|
703
|
-
|
|
718
|
+
compareDeps();
|
|
719
|
+
}
|
|
720
|
+
if (typeof shouldReloadDeps === 'object') {
|
|
721
|
+
matches[index] = match = {
|
|
722
|
+
...match,
|
|
723
|
+
shouldReloadDeps
|
|
724
|
+
};
|
|
704
725
|
}
|
|
705
|
-
}
|
|
706
726
|
|
|
707
|
-
|
|
708
|
-
|
|
727
|
+
// If the user doesn't want the route to reload, just
|
|
728
|
+
// resolve with the existing loader data
|
|
709
729
|
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
...match,
|
|
716
|
-
isFetching: true
|
|
717
|
-
};
|
|
718
|
-
const componentsPromise = Promise.all(componentTypes.map(async type => {
|
|
719
|
-
const component = route.options[type];
|
|
720
|
-
if (component?.preload) {
|
|
721
|
-
await component.preload();
|
|
730
|
+
if (!shouldLoad) {
|
|
731
|
+
loadPromise = Promise.resolve(match.loaderData);
|
|
732
|
+
} else {
|
|
733
|
+
if (match.fetchCount && match.status === 'success') {
|
|
734
|
+
resolve();
|
|
722
735
|
}
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
loadPromise = Promise.all([componentsPromise, loaderPromise]).then(d => d[1]);
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
matches[index] = match = {
|
|
729
|
-
...match,
|
|
730
|
-
loadPromise
|
|
731
|
-
};
|
|
732
|
-
if (!preload) {
|
|
733
|
-
updatePendingMatch(match);
|
|
734
|
-
}
|
|
735
|
-
let didShowPending = false;
|
|
736
|
-
const pendingMinMs = route.options.pendingMinMs ?? this.options.defaultPendingMinMs;
|
|
737
|
-
await new Promise(async resolve => {
|
|
738
|
-
// If the route has a pending component and a pendingMs option,
|
|
739
|
-
// forcefully show the pending component
|
|
740
|
-
if (pendingPromise) {
|
|
741
|
-
pendingPromise.then(() => {
|
|
742
|
-
if (latestPromise = checkLatest()) return;
|
|
743
|
-
didShowPending = true;
|
|
736
|
+
|
|
737
|
+
// Otherwise, load the route
|
|
744
738
|
matches[index] = match = {
|
|
745
739
|
...match,
|
|
746
|
-
|
|
740
|
+
isFetching: true,
|
|
741
|
+
fetchCount: match.fetchCount + 1
|
|
747
742
|
};
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
743
|
+
const componentsPromise = Promise.all(componentTypes.map(async type => {
|
|
744
|
+
const component = route.options[type];
|
|
745
|
+
if (component?.preload) {
|
|
746
|
+
await component.preload();
|
|
747
|
+
}
|
|
748
|
+
}));
|
|
749
|
+
const loaderPromise = route.options.loader?.(loaderContext);
|
|
750
|
+
loadPromise = Promise.all([componentsPromise, loaderPromise]).then(d => d[1]);
|
|
751
|
+
}
|
|
751
752
|
}
|
|
753
|
+
matches[index] = match = {
|
|
754
|
+
...match,
|
|
755
|
+
loadPromise
|
|
756
|
+
};
|
|
757
|
+
updateMatch(match);
|
|
752
758
|
try {
|
|
753
759
|
const loaderData = await loadPromise;
|
|
754
760
|
if (latestPromise = checkLatest()) return await latestPromise;
|
|
@@ -789,18 +795,38 @@ class Router {
|
|
|
789
795
|
// we already moved the pendingMatches to the matches
|
|
790
796
|
// state, so we need to update that specific match
|
|
791
797
|
if (didShowPending && pendingMinMs && match.showPending) {
|
|
792
|
-
|
|
793
|
-
...s,
|
|
794
|
-
matches: s.matches?.map(d => d.id === match.id ? match : d)
|
|
795
|
-
}));
|
|
798
|
+
updateMatch(match);
|
|
796
799
|
}
|
|
797
800
|
}
|
|
798
|
-
|
|
799
|
-
|
|
801
|
+
updateMatch(match);
|
|
802
|
+
};
|
|
803
|
+
if (match.fetchCount && match.status === 'success') {
|
|
804
|
+
// Background Fetching
|
|
805
|
+
fetch();
|
|
806
|
+
} else {
|
|
807
|
+
// Critical Fetching
|
|
808
|
+
|
|
809
|
+
// If we need to potentially show the pending component,
|
|
810
|
+
// start a timer to show it after the pendingMs
|
|
811
|
+
if (shouldPending) {
|
|
812
|
+
new Promise(r => setTimeout(r, pendingMs)).then(async () => {
|
|
813
|
+
if (latestPromise = checkLatest()) return latestPromise;
|
|
814
|
+
didShowPending = true;
|
|
815
|
+
matches[index] = match = {
|
|
816
|
+
...match,
|
|
817
|
+
showPending: true
|
|
818
|
+
};
|
|
819
|
+
updateMatch(match);
|
|
820
|
+
resolve();
|
|
821
|
+
});
|
|
800
822
|
}
|
|
801
|
-
|
|
802
|
-
}
|
|
803
|
-
|
|
823
|
+
await fetch();
|
|
824
|
+
}
|
|
825
|
+
resolve();
|
|
826
|
+
// No Fetching
|
|
827
|
+
|
|
828
|
+
resolve();
|
|
829
|
+
}));
|
|
804
830
|
});
|
|
805
831
|
await Promise.all(matchPromises);
|
|
806
832
|
return matches;
|
|
@@ -823,20 +849,32 @@ class Router {
|
|
|
823
849
|
toLocation: next,
|
|
824
850
|
pathChanged: pathDidChange
|
|
825
851
|
});
|
|
826
|
-
|
|
827
|
-
// Match the routes
|
|
828
|
-
let pendingMatches = this.matchRoutes(next.pathname, next.search, {
|
|
829
|
-
debug: true
|
|
830
|
-
});
|
|
852
|
+
let pendingMatches;
|
|
831
853
|
const previousMatches = this.state.matches;
|
|
854
|
+
this.__store.batch(() => {
|
|
855
|
+
this.__store.setState(s => ({
|
|
856
|
+
...s,
|
|
857
|
+
preloadMatches: s.preloadMatches.filter(d => {
|
|
858
|
+
return Date.now() - d.updatedAt < (this.options.defaultPreloadMaxAge ?? 3000);
|
|
859
|
+
})
|
|
860
|
+
}));
|
|
832
861
|
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
862
|
+
// Match the routes
|
|
863
|
+
pendingMatches = this.matchRoutes(next.pathname, next.search, {
|
|
864
|
+
debug: true
|
|
865
|
+
});
|
|
866
|
+
|
|
867
|
+
// Ingest the new matches
|
|
868
|
+
this.__store.setState(s => ({
|
|
869
|
+
...s,
|
|
870
|
+
isLoading: true,
|
|
871
|
+
location: next,
|
|
872
|
+
pendingMatches,
|
|
873
|
+
preloadMatches: s.preloadMatches.filter(d => {
|
|
874
|
+
return !pendingMatches.find(e => e.id === d.id);
|
|
875
|
+
})
|
|
876
|
+
}));
|
|
877
|
+
});
|
|
840
878
|
try {
|
|
841
879
|
try {
|
|
842
880
|
// Load the matches
|
|
@@ -894,6 +932,17 @@ class Router {
|
|
|
894
932
|
let matches = this.matchRoutes(next.pathname, next.search, {
|
|
895
933
|
throwOnError: true
|
|
896
934
|
});
|
|
935
|
+
const loadedMatchIds = Object.fromEntries([...this.state.matches, ...(this.state.pendingMatches ?? []), ...this.state.preloadMatches]?.map(d => [d.id, true]));
|
|
936
|
+
this.__store.batch(() => {
|
|
937
|
+
matches.forEach(match => {
|
|
938
|
+
if (!loadedMatchIds[match.id]) {
|
|
939
|
+
this.__store.setState(s => ({
|
|
940
|
+
...s,
|
|
941
|
+
preloadMatches: [...s.preloadMatches, match]
|
|
942
|
+
}));
|
|
943
|
+
}
|
|
944
|
+
});
|
|
945
|
+
});
|
|
897
946
|
matches = await this.loadMatches({
|
|
898
947
|
matches,
|
|
899
948
|
preload: true,
|
|
@@ -956,7 +1005,7 @@ class Router {
|
|
|
956
1005
|
dehydrate = () => {
|
|
957
1006
|
return {
|
|
958
1007
|
state: {
|
|
959
|
-
dehydratedMatches: this.state.matches.map(d => utils.pick(d, ['
|
|
1008
|
+
dehydratedMatches: this.state.matches.map(d => utils.pick(d, ['id', 'status', 'updatedAt', 'loaderData']))
|
|
960
1009
|
}
|
|
961
1010
|
};
|
|
962
1011
|
};
|
|
@@ -1019,6 +1068,7 @@ function getInitialRouterState(location) {
|
|
|
1019
1068
|
location,
|
|
1020
1069
|
matches: [],
|
|
1021
1070
|
pendingMatches: [],
|
|
1071
|
+
preloadMatches: [],
|
|
1022
1072
|
lastUpdated: Date.now()
|
|
1023
1073
|
};
|
|
1024
1074
|
}
|