@tanstack/react-router 0.0.1-beta.61 → 0.0.1-beta.62
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/index.js +37 -29
- package/build/cjs/index.js.map +1 -1
- package/build/esm/index.js +37 -29
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +1 -1
- package/build/stats-react.json +52 -52
- package/build/types/index.d.ts +16 -13
- package/build/umd/index.development.js +177 -148
- package/build/umd/index.development.js.map +1 -1
- package/build/umd/index.production.js +3 -3
- package/build/umd/index.production.js.map +1 -1
- package/package.json +3 -3
- package/src/index.tsx +74 -54
|
@@ -89,9 +89,9 @@
|
|
|
89
89
|
const previous = this.state;
|
|
90
90
|
this.state = this.options?.updateFn ? this.options.updateFn(previous)(updater) : updater(previous);
|
|
91
91
|
if (this.state === previous) return;
|
|
92
|
+
this.options?.onUpdate?.(this.state, previous);
|
|
92
93
|
this.queue.push(() => {
|
|
93
94
|
this.listeners.forEach(listener => listener(this.state, previous));
|
|
94
|
-
this.options?.onUpdate?.(this.state, previous);
|
|
95
95
|
});
|
|
96
96
|
this.#flush();
|
|
97
97
|
};
|
|
@@ -577,7 +577,9 @@
|
|
|
577
577
|
this.options = options || {};
|
|
578
578
|
this.isRoot = !options?.getParentRoute;
|
|
579
579
|
}
|
|
580
|
-
init =
|
|
580
|
+
init = opts => {
|
|
581
|
+
this.originalIndex = opts.originalIndex;
|
|
582
|
+
this.router = opts.router;
|
|
581
583
|
const allOptions = this.options;
|
|
582
584
|
const isRoot = !allOptions?.path && !allOptions?.id;
|
|
583
585
|
const parent = this.options?.getParentRoute?.();
|
|
@@ -625,6 +627,9 @@
|
|
|
625
627
|
constructor(options) {
|
|
626
628
|
super(options);
|
|
627
629
|
}
|
|
630
|
+
static withRouterContext = () => {
|
|
631
|
+
return options => new RootRoute(options);
|
|
632
|
+
};
|
|
628
633
|
}
|
|
629
634
|
|
|
630
635
|
// const rootRoute = new RootRoute({
|
|
@@ -689,8 +694,13 @@
|
|
|
689
694
|
routeSearch: {},
|
|
690
695
|
search: {},
|
|
691
696
|
status: 'idle'
|
|
697
|
+
}, {
|
|
698
|
+
onUpdate: next => {
|
|
699
|
+
this.state = next;
|
|
700
|
+
}
|
|
692
701
|
})
|
|
693
702
|
});
|
|
703
|
+
this.state = this.store.state;
|
|
694
704
|
if (!this.#hasLoaders()) {
|
|
695
705
|
this.store.setState(s => ({
|
|
696
706
|
...s,
|
|
@@ -698,12 +708,66 @@
|
|
|
698
708
|
}));
|
|
699
709
|
}
|
|
700
710
|
}
|
|
711
|
+
#hasLoaders = () => {
|
|
712
|
+
return !!(this.route.options.onLoad || componentTypes.some(d => this.route.options[d]?.preload));
|
|
713
|
+
};
|
|
714
|
+
__init = opts => {
|
|
715
|
+
// Validate the search params and stabilize them
|
|
716
|
+
this.parentMatch = opts.parentMatch;
|
|
717
|
+
const parentSearch = this.parentMatch?.state.search ?? this.router.state.latestLocation.search;
|
|
718
|
+
try {
|
|
719
|
+
const validator = typeof this.route.options.validateSearch === 'object' ? this.route.options.validateSearch.parse : this.route.options.validateSearch;
|
|
720
|
+
let nextSearch = validator?.(parentSearch) ?? {};
|
|
721
|
+
this.store.setState(s => ({
|
|
722
|
+
...s,
|
|
723
|
+
routeSearch: nextSearch,
|
|
724
|
+
search: {
|
|
725
|
+
...parentSearch,
|
|
726
|
+
...nextSearch
|
|
727
|
+
}
|
|
728
|
+
}));
|
|
729
|
+
componentTypes.map(async type => {
|
|
730
|
+
const component = this.route.options[type];
|
|
731
|
+
if (typeof this[type] !== 'function') {
|
|
732
|
+
this[type] = component;
|
|
733
|
+
}
|
|
734
|
+
});
|
|
735
|
+
const parent = this.parentMatch;
|
|
736
|
+
this.routeContext = this.route.options.getContext?.({
|
|
737
|
+
parentContext: parent?.routeContext,
|
|
738
|
+
context: parent?.context,
|
|
739
|
+
params: this.params,
|
|
740
|
+
search: this.state.search
|
|
741
|
+
}) || {};
|
|
742
|
+
this.context = parent ? {
|
|
743
|
+
...parent.context,
|
|
744
|
+
...this.routeContext
|
|
745
|
+
} : {
|
|
746
|
+
...this.router?.options.context,
|
|
747
|
+
...this.routeContext
|
|
748
|
+
};
|
|
749
|
+
} catch (err) {
|
|
750
|
+
console.error(err);
|
|
751
|
+
const error = new Error('Invalid search params found', {
|
|
752
|
+
cause: err
|
|
753
|
+
});
|
|
754
|
+
error.code = 'INVALID_SEARCH_PARAMS';
|
|
755
|
+
this.store.setState(s => ({
|
|
756
|
+
...s,
|
|
757
|
+
status: 'error',
|
|
758
|
+
error: error
|
|
759
|
+
}));
|
|
760
|
+
|
|
761
|
+
// Do not proceed with loading the route
|
|
762
|
+
return;
|
|
763
|
+
}
|
|
764
|
+
};
|
|
701
765
|
cancel = () => {
|
|
702
766
|
this.abortController?.abort();
|
|
703
767
|
};
|
|
704
768
|
load = async opts => {
|
|
705
769
|
// If the match is invalid, errored or idle, trigger it to load
|
|
706
|
-
if (this.
|
|
770
|
+
if (this.state.status !== 'pending') {
|
|
707
771
|
await this.fetch(opts);
|
|
708
772
|
}
|
|
709
773
|
};
|
|
@@ -720,7 +784,7 @@
|
|
|
720
784
|
// If the match was in an error state, set it
|
|
721
785
|
// to a loading state again. Otherwise, keep it
|
|
722
786
|
// as loading or resolved
|
|
723
|
-
if (this.
|
|
787
|
+
if (this.state.status === 'idle') {
|
|
724
788
|
this.store.setState(s => ({
|
|
725
789
|
...s,
|
|
726
790
|
status: 'pending'
|
|
@@ -742,9 +806,11 @@
|
|
|
742
806
|
if (this.route.options.onLoad) {
|
|
743
807
|
return this.route.options.onLoad({
|
|
744
808
|
params: this.params,
|
|
745
|
-
search: this.
|
|
809
|
+
search: this.state.search,
|
|
746
810
|
signal: this.abortController.signal,
|
|
747
|
-
preload: !!opts?.preload
|
|
811
|
+
preload: !!opts?.preload,
|
|
812
|
+
routeContext: this.routeContext,
|
|
813
|
+
context: this.context
|
|
748
814
|
});
|
|
749
815
|
}
|
|
750
816
|
return;
|
|
@@ -772,50 +838,6 @@
|
|
|
772
838
|
});
|
|
773
839
|
return this.__loadPromise;
|
|
774
840
|
};
|
|
775
|
-
#hasLoaders = () => {
|
|
776
|
-
return !!(this.route.options.onLoad || componentTypes.some(d => this.route.options[d]?.preload));
|
|
777
|
-
};
|
|
778
|
-
__setParentMatch = parentMatch => {
|
|
779
|
-
if (!this.parentMatch && parentMatch) {
|
|
780
|
-
this.parentMatch = parentMatch;
|
|
781
|
-
}
|
|
782
|
-
};
|
|
783
|
-
__validate = () => {
|
|
784
|
-
// Validate the search params and stabilize them
|
|
785
|
-
const parentSearch = this.parentMatch?.store.state.search ?? this.router.store.state.latestLocation.search;
|
|
786
|
-
try {
|
|
787
|
-
const validator = typeof this.route.options.validateSearch === 'object' ? this.route.options.validateSearch.parse : this.route.options.validateSearch;
|
|
788
|
-
let nextSearch = validator?.(parentSearch) ?? {};
|
|
789
|
-
this.store.setState(s => ({
|
|
790
|
-
...s,
|
|
791
|
-
routeSearch: nextSearch,
|
|
792
|
-
search: {
|
|
793
|
-
...parentSearch,
|
|
794
|
-
...nextSearch
|
|
795
|
-
}
|
|
796
|
-
}));
|
|
797
|
-
componentTypes.map(async type => {
|
|
798
|
-
const component = this.route.options[type];
|
|
799
|
-
if (typeof this[type] !== 'function') {
|
|
800
|
-
this[type] = component;
|
|
801
|
-
}
|
|
802
|
-
});
|
|
803
|
-
} catch (err) {
|
|
804
|
-
console.error(err);
|
|
805
|
-
const error = new Error('Invalid search params found', {
|
|
806
|
-
cause: err
|
|
807
|
-
});
|
|
808
|
-
error.code = 'INVALID_SEARCH_PARAMS';
|
|
809
|
-
this.store.setState(s => ({
|
|
810
|
-
...s,
|
|
811
|
-
status: 'error',
|
|
812
|
-
error: error
|
|
813
|
-
}));
|
|
814
|
-
|
|
815
|
-
// Do not proceed with loading the route
|
|
816
|
-
return;
|
|
817
|
-
}
|
|
818
|
-
};
|
|
819
841
|
}
|
|
820
842
|
|
|
821
843
|
const defaultParseSearch = parseSearchWith(JSON.parse);
|
|
@@ -900,7 +922,12 @@
|
|
|
900
922
|
parseSearch: options?.parseSearch ?? defaultParseSearch,
|
|
901
923
|
fetchServerDataFn: options?.fetchServerDataFn ?? defaultFetchServerDataFn
|
|
902
924
|
};
|
|
903
|
-
this.store = new Store(getInitialRouterState()
|
|
925
|
+
this.store = new Store(getInitialRouterState(), {
|
|
926
|
+
onUpdate: state => {
|
|
927
|
+
this.state = state;
|
|
928
|
+
}
|
|
929
|
+
});
|
|
930
|
+
this.state = this.store.state;
|
|
904
931
|
this.basepath = '';
|
|
905
932
|
this.update(options);
|
|
906
933
|
|
|
@@ -914,7 +941,7 @@
|
|
|
914
941
|
// Mount only does anything on the client
|
|
915
942
|
if (!isServer) {
|
|
916
943
|
// If the router matches are empty, load the matches
|
|
917
|
-
if (!this.
|
|
944
|
+
if (!this.state.currentMatches.length) {
|
|
918
945
|
this.load();
|
|
919
946
|
}
|
|
920
947
|
const visibilityChangeEvent = 'visibilitychange';
|
|
@@ -953,7 +980,9 @@
|
|
|
953
980
|
currentLocation: parsedLocation
|
|
954
981
|
}));
|
|
955
982
|
this.#unsubHistory = this.history.listen(() => {
|
|
956
|
-
this.load(
|
|
983
|
+
this.load({
|
|
984
|
+
next: this.#parseLocation(this.state.latestLocation)
|
|
985
|
+
});
|
|
957
986
|
});
|
|
958
987
|
}
|
|
959
988
|
const {
|
|
@@ -979,11 +1008,11 @@
|
|
|
979
1008
|
});
|
|
980
1009
|
};
|
|
981
1010
|
cancelMatches = () => {
|
|
982
|
-
[...this.
|
|
1011
|
+
[...this.state.currentMatches, ...(this.state.pendingMatches || [])].forEach(match => {
|
|
983
1012
|
match.cancel();
|
|
984
1013
|
});
|
|
985
1014
|
};
|
|
986
|
-
load = async
|
|
1015
|
+
load = async opts => {
|
|
987
1016
|
let now = Date.now();
|
|
988
1017
|
const startedAt = now;
|
|
989
1018
|
this.startedLoadingAt = startedAt;
|
|
@@ -992,29 +1021,31 @@
|
|
|
992
1021
|
this.cancelMatches();
|
|
993
1022
|
let matches;
|
|
994
1023
|
this.store.batch(() => {
|
|
995
|
-
if (next) {
|
|
1024
|
+
if (opts?.next) {
|
|
996
1025
|
// Ingest the new location
|
|
997
1026
|
this.store.setState(s => ({
|
|
998
1027
|
...s,
|
|
999
|
-
latestLocation: next
|
|
1028
|
+
latestLocation: opts.next
|
|
1000
1029
|
}));
|
|
1001
1030
|
}
|
|
1002
1031
|
|
|
1003
1032
|
// Match the routes
|
|
1004
|
-
matches = this.matchRoutes(this.
|
|
1033
|
+
matches = this.matchRoutes(this.state.latestLocation.pathname, {
|
|
1005
1034
|
strictParseParams: true
|
|
1006
1035
|
});
|
|
1007
1036
|
this.store.setState(s => ({
|
|
1008
1037
|
...s,
|
|
1009
1038
|
status: 'pending',
|
|
1010
1039
|
pendingMatches: matches,
|
|
1011
|
-
pendingLocation: this.
|
|
1040
|
+
pendingLocation: this.state.latestLocation
|
|
1012
1041
|
}));
|
|
1013
1042
|
});
|
|
1014
1043
|
|
|
1015
1044
|
// Load the matches
|
|
1016
1045
|
try {
|
|
1017
|
-
await this.loadMatches(matches
|
|
1046
|
+
await this.loadMatches(matches
|
|
1047
|
+
// opts
|
|
1048
|
+
);
|
|
1018
1049
|
} catch (err) {
|
|
1019
1050
|
console.warn(err);
|
|
1020
1051
|
invariant(false, 'Matches failed to load due to error above ☝️. Navigation cancelled!');
|
|
@@ -1023,7 +1054,7 @@
|
|
|
1023
1054
|
// Ignore side-effects of outdated side-effects
|
|
1024
1055
|
return this.navigationPromise;
|
|
1025
1056
|
}
|
|
1026
|
-
const previousMatches = this.
|
|
1057
|
+
const previousMatches = this.state.currentMatches;
|
|
1027
1058
|
const exiting = [],
|
|
1028
1059
|
staying = [];
|
|
1029
1060
|
previousMatches.forEach(d => {
|
|
@@ -1040,11 +1071,11 @@
|
|
|
1040
1071
|
exiting.forEach(d => {
|
|
1041
1072
|
d.__onExit?.({
|
|
1042
1073
|
params: d.params,
|
|
1043
|
-
search: d.
|
|
1074
|
+
search: d.state.routeSearch
|
|
1044
1075
|
});
|
|
1045
1076
|
|
|
1046
1077
|
// Clear non-loading error states when match leaves
|
|
1047
|
-
if (d.
|
|
1078
|
+
if (d.state.status === 'error') {
|
|
1048
1079
|
this.store.setState(s => ({
|
|
1049
1080
|
...s,
|
|
1050
1081
|
status: 'idle',
|
|
@@ -1055,21 +1086,19 @@
|
|
|
1055
1086
|
staying.forEach(d => {
|
|
1056
1087
|
d.route.options.onTransition?.({
|
|
1057
1088
|
params: d.params,
|
|
1058
|
-
search: d.
|
|
1089
|
+
search: d.state.routeSearch
|
|
1059
1090
|
});
|
|
1060
1091
|
});
|
|
1061
1092
|
entering.forEach(d => {
|
|
1062
1093
|
d.__onExit = d.route.options.onLoaded?.({
|
|
1063
1094
|
params: d.params,
|
|
1064
|
-
search: d.
|
|
1095
|
+
search: d.state.search
|
|
1065
1096
|
});
|
|
1066
|
-
// delete this.store.state.matchCache[d.id] // TODO:
|
|
1067
1097
|
});
|
|
1068
|
-
|
|
1069
1098
|
this.store.setState(s => ({
|
|
1070
1099
|
...s,
|
|
1071
1100
|
status: 'idle',
|
|
1072
|
-
currentLocation: this.
|
|
1101
|
+
currentLocation: this.state.latestLocation,
|
|
1073
1102
|
currentMatches: matches,
|
|
1074
1103
|
pendingLocation: undefined,
|
|
1075
1104
|
pendingMatches: undefined
|
|
@@ -1082,7 +1111,7 @@
|
|
|
1082
1111
|
invariant(route, `Route with id "${id}" not found`);
|
|
1083
1112
|
return route;
|
|
1084
1113
|
};
|
|
1085
|
-
loadRoute = async (navigateOpts = this.
|
|
1114
|
+
loadRoute = async (navigateOpts = this.state.latestLocation) => {
|
|
1086
1115
|
const next = this.buildNext(navigateOpts);
|
|
1087
1116
|
const matches = this.matchRoutes(next.pathname, {
|
|
1088
1117
|
strictParseParams: true
|
|
@@ -1090,7 +1119,7 @@
|
|
|
1090
1119
|
await this.loadMatches(matches);
|
|
1091
1120
|
return matches;
|
|
1092
1121
|
};
|
|
1093
|
-
preloadRoute = async (navigateOpts = this.
|
|
1122
|
+
preloadRoute = async (navigateOpts = this.state.latestLocation) => {
|
|
1094
1123
|
const next = this.buildNext(navigateOpts);
|
|
1095
1124
|
const matches = this.matchRoutes(next.pathname, {
|
|
1096
1125
|
strictParseParams: true
|
|
@@ -1105,7 +1134,7 @@
|
|
|
1105
1134
|
if (!this.routeTree) {
|
|
1106
1135
|
return matches;
|
|
1107
1136
|
}
|
|
1108
|
-
const existingMatches = [...this.
|
|
1137
|
+
const existingMatches = [...this.state.currentMatches, ...(this.state.pendingMatches ?? [])];
|
|
1109
1138
|
const findInRouteTree = async routes => {
|
|
1110
1139
|
const parentMatch = last(matches);
|
|
1111
1140
|
let params = parentMatch?.params ?? {};
|
|
@@ -1151,9 +1180,7 @@
|
|
|
1151
1180
|
matchingRoutes.forEach(foundRoute => {
|
|
1152
1181
|
const interpolatedPath = interpolatePath(foundRoute.path, params);
|
|
1153
1182
|
const matchId = interpolatePath(foundRoute.id, params, true);
|
|
1154
|
-
const match = existingMatches.find(d => d.id === matchId) ||
|
|
1155
|
-
// this.store.state.matchCache[matchId]?.match || // TODO:
|
|
1156
|
-
new RouteMatch(this, foundRoute, {
|
|
1183
|
+
const match = existingMatches.find(d => d.id === matchId) || new RouteMatch(this, foundRoute, {
|
|
1157
1184
|
id: matchId,
|
|
1158
1185
|
params,
|
|
1159
1186
|
pathname: joinPaths([this.basepath, interpolatedPath])
|
|
@@ -1169,14 +1196,8 @@
|
|
|
1169
1196
|
findInRouteTree([this.routeTree]);
|
|
1170
1197
|
return matches;
|
|
1171
1198
|
};
|
|
1172
|
-
loadMatches = async (resolvedMatches,
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
// this.cleanMatchCache()
|
|
1176
|
-
resolvedMatches.forEach(async match => {
|
|
1177
|
-
// Validate the match (loads search params etc)
|
|
1178
|
-
match.__validate();
|
|
1179
|
-
});
|
|
1199
|
+
loadMatches = async (resolvedMatches, opts) => {
|
|
1200
|
+
initMatches(resolvedMatches);
|
|
1180
1201
|
|
|
1181
1202
|
// Check each match middleware to see if the route can be accessed
|
|
1182
1203
|
await Promise.all(resolvedMatches.map(async match => {
|
|
@@ -1186,7 +1207,7 @@
|
|
|
1186
1207
|
match
|
|
1187
1208
|
});
|
|
1188
1209
|
} catch (err) {
|
|
1189
|
-
if (!
|
|
1210
|
+
if (!opts?.preload) {
|
|
1190
1211
|
match.route.options.onLoadError?.(err);
|
|
1191
1212
|
}
|
|
1192
1213
|
throw err;
|
|
@@ -1194,14 +1215,16 @@
|
|
|
1194
1215
|
}));
|
|
1195
1216
|
const matchPromises = resolvedMatches.map(async (match, index) => {
|
|
1196
1217
|
const prevMatch = resolvedMatches[1];
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1218
|
+
match.state.search;
|
|
1219
|
+
|
|
1220
|
+
// if (opts?.filter && !opts.filter(match)) {
|
|
1221
|
+
// return
|
|
1222
|
+
// }
|
|
1223
|
+
|
|
1201
1224
|
match.load({
|
|
1202
|
-
preload:
|
|
1225
|
+
preload: opts?.preload
|
|
1203
1226
|
});
|
|
1204
|
-
if (match.
|
|
1227
|
+
if (match.state.status !== 'success' && match.__loadPromise) {
|
|
1205
1228
|
// Wait for the first sign of activity from the match
|
|
1206
1229
|
await match.__loadPromise;
|
|
1207
1230
|
}
|
|
@@ -1258,15 +1281,15 @@
|
|
|
1258
1281
|
};
|
|
1259
1282
|
const next = this.buildNext(location);
|
|
1260
1283
|
if (opts?.pending) {
|
|
1261
|
-
if (!this.
|
|
1284
|
+
if (!this.state.pendingLocation) {
|
|
1262
1285
|
return false;
|
|
1263
1286
|
}
|
|
1264
|
-
return matchPathname(this.basepath, this.
|
|
1287
|
+
return matchPathname(this.basepath, this.state.pendingLocation.pathname, {
|
|
1265
1288
|
...opts,
|
|
1266
1289
|
to: next.pathname
|
|
1267
1290
|
});
|
|
1268
1291
|
}
|
|
1269
|
-
return matchPathname(this.basepath, this.
|
|
1292
|
+
return matchPathname(this.basepath, this.state.currentLocation.pathname, {
|
|
1270
1293
|
...opts,
|
|
1271
1294
|
to: next.pathname
|
|
1272
1295
|
});
|
|
@@ -1312,11 +1335,11 @@
|
|
|
1312
1335
|
const preloadDelay = userPreloadDelay ?? this.options.defaultPreloadDelay ?? 0;
|
|
1313
1336
|
|
|
1314
1337
|
// Compare path/hash for matches
|
|
1315
|
-
const pathIsEqual = this.
|
|
1316
|
-
const currentPathSplit = this.
|
|
1338
|
+
const pathIsEqual = this.state.currentLocation.pathname === next.pathname;
|
|
1339
|
+
const currentPathSplit = this.state.currentLocation.pathname.split('/');
|
|
1317
1340
|
const nextPathSplit = next.pathname.split('/');
|
|
1318
1341
|
const pathIsFuzzyEqual = nextPathSplit.every((d, i) => d === currentPathSplit[i]);
|
|
1319
|
-
const hashIsEqual = this.
|
|
1342
|
+
const hashIsEqual = this.state.currentLocation.hash === next.hash;
|
|
1320
1343
|
// Combine the matches based on user options
|
|
1321
1344
|
const pathTest = activeOptions?.exact ? pathIsEqual : pathIsFuzzyEqual;
|
|
1322
1345
|
const hashTest = activeOptions?.includeHash ? hashIsEqual : true;
|
|
@@ -1379,21 +1402,18 @@
|
|
|
1379
1402
|
dehydrate = () => {
|
|
1380
1403
|
return {
|
|
1381
1404
|
state: {
|
|
1382
|
-
...pick(this.
|
|
1383
|
-
currentMatches: this.
|
|
1405
|
+
...pick(this.state, ['latestLocation', 'currentLocation', 'status', 'lastUpdated']),
|
|
1406
|
+
currentMatches: this.state.currentMatches.map(match => ({
|
|
1384
1407
|
id: match.id,
|
|
1385
1408
|
state: {
|
|
1386
|
-
|
|
1409
|
+
status: match.state.status
|
|
1387
1410
|
}
|
|
1388
1411
|
}))
|
|
1389
|
-
}
|
|
1390
|
-
context: this.options.context
|
|
1412
|
+
}
|
|
1391
1413
|
};
|
|
1392
1414
|
};
|
|
1393
1415
|
hydrate = dehydratedRouter => {
|
|
1394
1416
|
this.store.setState(s => {
|
|
1395
|
-
this.options.context = dehydratedRouter.context;
|
|
1396
|
-
|
|
1397
1417
|
// Match the routes
|
|
1398
1418
|
const currentMatches = this.matchRoutes(dehydratedRouter.state.latestLocation.pathname, {
|
|
1399
1419
|
strictParseParams: true
|
|
@@ -1406,7 +1426,7 @@
|
|
|
1406
1426
|
...dehydratedMatch.state
|
|
1407
1427
|
}));
|
|
1408
1428
|
});
|
|
1409
|
-
currentMatches
|
|
1429
|
+
initMatches(currentMatches);
|
|
1410
1430
|
return {
|
|
1411
1431
|
...s,
|
|
1412
1432
|
...dehydratedRouter.state,
|
|
@@ -1417,9 +1437,10 @@
|
|
|
1417
1437
|
#buildRouteTree = routeTree => {
|
|
1418
1438
|
const recurseRoutes = routes => {
|
|
1419
1439
|
routes.forEach((route, i) => {
|
|
1420
|
-
route.init(
|
|
1421
|
-
|
|
1422
|
-
|
|
1440
|
+
route.init({
|
|
1441
|
+
originalIndex: i,
|
|
1442
|
+
router: this
|
|
1443
|
+
});
|
|
1423
1444
|
const existingRoute = this.routesById[route.id];
|
|
1424
1445
|
if (existingRoute) {
|
|
1425
1446
|
{
|
|
@@ -1457,9 +1478,9 @@
|
|
|
1457
1478
|
this.load();
|
|
1458
1479
|
};
|
|
1459
1480
|
#buildLocation = (dest = {}) => {
|
|
1460
|
-
const fromPathname = dest.fromCurrent ? this.
|
|
1481
|
+
const fromPathname = dest.fromCurrent ? this.state.latestLocation.pathname : dest.from ?? this.state.latestLocation.pathname;
|
|
1461
1482
|
let pathname = resolvePath(this.basepath ?? '/', fromPathname, `${dest.to ?? '.'}`);
|
|
1462
|
-
const fromMatches = this.matchRoutes(this.
|
|
1483
|
+
const fromMatches = this.matchRoutes(this.state.latestLocation.pathname, {
|
|
1463
1484
|
strictParseParams: true
|
|
1464
1485
|
});
|
|
1465
1486
|
const toMatches = this.matchRoutes(pathname);
|
|
@@ -1475,7 +1496,7 @@
|
|
|
1475
1496
|
pathname = interpolatePath(pathname, nextParams ?? {});
|
|
1476
1497
|
|
|
1477
1498
|
// Pre filters first
|
|
1478
|
-
const preFilteredSearch = dest.__preSearchFilters?.length ? dest.__preSearchFilters?.reduce((prev, next) => next(prev), this.
|
|
1499
|
+
const preFilteredSearch = dest.__preSearchFilters?.length ? dest.__preSearchFilters?.reduce((prev, next) => next(prev), this.state.latestLocation.search) : this.state.latestLocation.search;
|
|
1479
1500
|
|
|
1480
1501
|
// Then the link/navigate function
|
|
1481
1502
|
const destSearch = dest.search === true ? preFilteredSearch // Preserve resolvedFrom true
|
|
@@ -1485,15 +1506,15 @@
|
|
|
1485
1506
|
|
|
1486
1507
|
// Then post filters
|
|
1487
1508
|
const postFilteredSearch = dest.__postSearchFilters?.length ? dest.__postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
|
|
1488
|
-
const search = replaceEqualDeep(this.
|
|
1509
|
+
const search = replaceEqualDeep(this.state.latestLocation.search, postFilteredSearch);
|
|
1489
1510
|
const searchStr = this.options.stringifySearch(search);
|
|
1490
|
-
let hash = dest.hash === true ? this.
|
|
1511
|
+
let hash = dest.hash === true ? this.state.latestLocation.hash : functionalUpdate(dest.hash, this.state.latestLocation.hash);
|
|
1491
1512
|
hash = hash ? `#${hash}` : '';
|
|
1492
1513
|
return {
|
|
1493
1514
|
pathname,
|
|
1494
1515
|
search,
|
|
1495
1516
|
searchStr,
|
|
1496
|
-
state: this.
|
|
1517
|
+
state: this.state.latestLocation.state,
|
|
1497
1518
|
hash,
|
|
1498
1519
|
href: `${pathname}${searchStr}${hash}`,
|
|
1499
1520
|
key: dest.key
|
|
@@ -1507,7 +1528,7 @@
|
|
|
1507
1528
|
if (!location.replace) {
|
|
1508
1529
|
nextAction = 'push';
|
|
1509
1530
|
}
|
|
1510
|
-
const isSameUrl = this.
|
|
1531
|
+
const isSameUrl = this.state.latestLocation.href === next.href;
|
|
1511
1532
|
if (isSameUrl && !next.key) {
|
|
1512
1533
|
nextAction = 'replace';
|
|
1513
1534
|
}
|
|
@@ -1517,7 +1538,7 @@
|
|
|
1517
1538
|
...next.state
|
|
1518
1539
|
});
|
|
1519
1540
|
|
|
1520
|
-
// this.load(this.#parseLocation(this.
|
|
1541
|
+
// this.load(this.#parseLocation(this.state.latestLocation))
|
|
1521
1542
|
|
|
1522
1543
|
return this.navigationPromise = new Promise(resolve => {
|
|
1523
1544
|
const previousNavigationResolve = this.resolveNavigation;
|
|
@@ -1543,12 +1564,12 @@
|
|
|
1543
1564
|
function isCtrlEvent(e) {
|
|
1544
1565
|
return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
|
|
1545
1566
|
}
|
|
1546
|
-
function
|
|
1567
|
+
function initMatches(matches) {
|
|
1547
1568
|
matches.forEach((match, index) => {
|
|
1548
|
-
const
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
}
|
|
1569
|
+
const parentMatch = matches[index - 1];
|
|
1570
|
+
match.__init({
|
|
1571
|
+
parentMatch
|
|
1572
|
+
});
|
|
1552
1573
|
});
|
|
1553
1574
|
}
|
|
1554
1575
|
|
|
@@ -1624,7 +1645,7 @@
|
|
|
1624
1645
|
//
|
|
1625
1646
|
|
|
1626
1647
|
function useLinkProps(options) {
|
|
1627
|
-
const router =
|
|
1648
|
+
const router = useRouterContext();
|
|
1628
1649
|
const {
|
|
1629
1650
|
// custom props
|
|
1630
1651
|
type,
|
|
@@ -1749,7 +1770,7 @@
|
|
|
1749
1770
|
...rest
|
|
1750
1771
|
}) {
|
|
1751
1772
|
router.update(rest);
|
|
1752
|
-
const currentMatches = useStore(router.store, s => s.currentMatches
|
|
1773
|
+
const currentMatches = useStore(router.store, s => s.currentMatches);
|
|
1753
1774
|
React__namespace.useEffect(router.mount, [router]);
|
|
1754
1775
|
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(routerContext.Provider, {
|
|
1755
1776
|
value: {
|
|
@@ -1759,22 +1780,24 @@
|
|
|
1759
1780
|
value: [undefined, ...currentMatches]
|
|
1760
1781
|
}, /*#__PURE__*/React__namespace.createElement(Outlet, null))));
|
|
1761
1782
|
}
|
|
1762
|
-
function
|
|
1783
|
+
function useRouterContext() {
|
|
1763
1784
|
const value = React__namespace.useContext(routerContext);
|
|
1764
1785
|
warning(!value, 'useRouter must be used inside a <Router> component!');
|
|
1786
|
+
useStore(value.router.store);
|
|
1765
1787
|
return value.router;
|
|
1766
1788
|
}
|
|
1767
|
-
function
|
|
1768
|
-
const router =
|
|
1769
|
-
|
|
1789
|
+
function useRouter(track, shallow) {
|
|
1790
|
+
const router = useRouterContext();
|
|
1791
|
+
useStore(router.store, track, shallow);
|
|
1792
|
+
return router;
|
|
1770
1793
|
}
|
|
1771
1794
|
function useMatches() {
|
|
1772
1795
|
return React__namespace.useContext(matchesContext);
|
|
1773
1796
|
}
|
|
1774
1797
|
function useMatch(opts) {
|
|
1775
|
-
const router =
|
|
1798
|
+
const router = useRouterContext();
|
|
1776
1799
|
const nearestMatch = useMatches()[0];
|
|
1777
|
-
const match = opts?.from ? router.
|
|
1800
|
+
const match = opts?.from ? router.state.currentMatches.find(d => d.route.id === opts?.from) : nearestMatch;
|
|
1778
1801
|
invariant(match, `Could not find ${opts?.from ? `an active match from "${opts.from}"` : 'a nearest match!'}`);
|
|
1779
1802
|
if (opts?.strict ?? true) {
|
|
1780
1803
|
invariant(nearestMatch.route.id == match?.route.id, `useMatch("${match?.route.id}") is being called in a component that is meant to render the '${nearestMatch.route.id}' route. Did you mean to 'useMatch("${match?.route.id}", { strict: false })' or 'useRoute("${match?.route.id}")' instead?`);
|
|
@@ -1783,26 +1806,26 @@
|
|
|
1783
1806
|
return match;
|
|
1784
1807
|
}
|
|
1785
1808
|
function useRoute(routeId) {
|
|
1786
|
-
const router =
|
|
1809
|
+
const router = useRouterContext();
|
|
1787
1810
|
const resolvedRoute = router.getRoute(routeId);
|
|
1788
1811
|
invariant(resolvedRoute, `Could not find a route for route "${routeId}"! Did you forget to add it to your route config?`);
|
|
1789
1812
|
return resolvedRoute;
|
|
1790
1813
|
}
|
|
1791
1814
|
function useSearch(opts) {
|
|
1792
1815
|
const match = useMatch(opts);
|
|
1793
|
-
useStore(match.store, d => opts?.track?.(d.search) ?? d.search);
|
|
1794
|
-
return match.
|
|
1816
|
+
useStore(match.store, d => opts?.track?.(d.search) ?? d.search, true);
|
|
1817
|
+
return match.state.search;
|
|
1795
1818
|
}
|
|
1796
1819
|
function useParams(opts) {
|
|
1797
|
-
const router =
|
|
1820
|
+
const router = useRouterContext();
|
|
1798
1821
|
useStore(router.store, d => {
|
|
1799
1822
|
const params = last(d.currentMatches)?.params;
|
|
1800
1823
|
return opts?.track?.(params) ?? params;
|
|
1801
|
-
});
|
|
1802
|
-
return last(router.
|
|
1824
|
+
}, true);
|
|
1825
|
+
return last(router.state.currentMatches)?.params;
|
|
1803
1826
|
}
|
|
1804
1827
|
function useNavigate(defaultOpts) {
|
|
1805
|
-
const router =
|
|
1828
|
+
const router = useRouterContext();
|
|
1806
1829
|
return opts => {
|
|
1807
1830
|
return router.navigate({
|
|
1808
1831
|
...defaultOpts,
|
|
@@ -1811,7 +1834,7 @@
|
|
|
1811
1834
|
};
|
|
1812
1835
|
}
|
|
1813
1836
|
function useMatchRoute() {
|
|
1814
|
-
const router =
|
|
1837
|
+
const router = useRouterContext();
|
|
1815
1838
|
return opts => {
|
|
1816
1839
|
const {
|
|
1817
1840
|
pending,
|
|
@@ -1850,17 +1873,17 @@
|
|
|
1850
1873
|
matches,
|
|
1851
1874
|
match
|
|
1852
1875
|
}) {
|
|
1853
|
-
const router =
|
|
1854
|
-
useStore(match.store);
|
|
1876
|
+
const router = useRouterContext();
|
|
1877
|
+
useStore(match.store, store => [store.status, store.error], true);
|
|
1855
1878
|
const defaultPending = React__namespace.useCallback(() => null, []);
|
|
1856
1879
|
const Inner = React__namespace.useCallback(props => {
|
|
1857
|
-
if (props.match.
|
|
1858
|
-
throw props.match.
|
|
1880
|
+
if (props.match.state.status === 'error') {
|
|
1881
|
+
throw props.match.state.error;
|
|
1859
1882
|
}
|
|
1860
|
-
if (props.match.
|
|
1883
|
+
if (props.match.state.status === 'success') {
|
|
1861
1884
|
return /*#__PURE__*/React__namespace.createElement(props.match.component ?? router.options.defaultComponent ?? Outlet);
|
|
1862
1885
|
}
|
|
1863
|
-
if (props.match.
|
|
1886
|
+
if (props.match.state.status === 'pending') {
|
|
1864
1887
|
throw props.match.__loadPromise;
|
|
1865
1888
|
}
|
|
1866
1889
|
invariant(false, 'Idle routeMatch status encountered during rendering! You should never see this. File an issue!');
|
|
@@ -1869,7 +1892,7 @@
|
|
|
1869
1892
|
const errorComponent = match.errorComponent ?? router.options.defaultErrorComponent;
|
|
1870
1893
|
return /*#__PURE__*/React__namespace.createElement(matchesContext.Provider, {
|
|
1871
1894
|
value: matches
|
|
1872
|
-
}, /*#__PURE__*/React__namespace.createElement(React__namespace.Suspense, {
|
|
1895
|
+
}, match.route.options.wrapInSuspense ?? true ? /*#__PURE__*/React__namespace.createElement(React__namespace.Suspense, {
|
|
1873
1896
|
fallback: /*#__PURE__*/React__namespace.createElement(PendingComponent, null)
|
|
1874
1897
|
}, /*#__PURE__*/React__namespace.createElement(CatchBoundary, {
|
|
1875
1898
|
key: match.route.id,
|
|
@@ -1877,7 +1900,13 @@
|
|
|
1877
1900
|
match: match
|
|
1878
1901
|
}, /*#__PURE__*/React__namespace.createElement(Inner, {
|
|
1879
1902
|
match: match
|
|
1880
|
-
})))
|
|
1903
|
+
}))) : /*#__PURE__*/React__namespace.createElement(CatchBoundary, {
|
|
1904
|
+
key: match.route.id,
|
|
1905
|
+
errorComponent: errorComponent,
|
|
1906
|
+
match: match
|
|
1907
|
+
}, /*#__PURE__*/React__namespace.createElement(Inner, {
|
|
1908
|
+
match: match
|
|
1909
|
+
})));
|
|
1881
1910
|
}
|
|
1882
1911
|
|
|
1883
1912
|
// This is the messiest thing ever... I'm either seriously tired (likely) or
|
|
@@ -1906,17 +1935,17 @@
|
|
|
1906
1935
|
}
|
|
1907
1936
|
function CatchBoundaryInner(props) {
|
|
1908
1937
|
const [activeErrorState, setActiveErrorState] = React__namespace.useState(props.errorState);
|
|
1909
|
-
const router =
|
|
1938
|
+
const router = useRouterContext();
|
|
1910
1939
|
const errorComponent = props.errorComponent ?? DefaultErrorBoundary;
|
|
1911
1940
|
const prevKeyRef = React__namespace.useRef('');
|
|
1912
1941
|
React__namespace.useEffect(() => {
|
|
1913
1942
|
if (activeErrorState) {
|
|
1914
|
-
if (router.
|
|
1943
|
+
if (router.state.currentLocation.key !== prevKeyRef.current) {
|
|
1915
1944
|
setActiveErrorState({});
|
|
1916
1945
|
}
|
|
1917
1946
|
}
|
|
1918
|
-
prevKeyRef.current = router.
|
|
1919
|
-
}, [activeErrorState, router.
|
|
1947
|
+
prevKeyRef.current = router.state.currentLocation.key;
|
|
1948
|
+
}, [activeErrorState, router.state.currentLocation.key]);
|
|
1920
1949
|
React__namespace.useEffect(() => {
|
|
1921
1950
|
if (props.errorState.error) {
|
|
1922
1951
|
setActiveErrorState(props.errorState);
|
|
@@ -2030,7 +2059,7 @@
|
|
|
2030
2059
|
exports.useParams = useParams;
|
|
2031
2060
|
exports.useRoute = useRoute;
|
|
2032
2061
|
exports.useRouter = useRouter;
|
|
2033
|
-
exports.
|
|
2062
|
+
exports.useRouterContext = useRouterContext;
|
|
2034
2063
|
exports.useSearch = useSearch;
|
|
2035
2064
|
exports.useStore = useStore;
|
|
2036
2065
|
exports.warning = warning;
|