@tanstack/react-router 0.0.1-beta.227 → 0.0.1-beta.229
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 +15 -13
- package/build/cjs/Matches.js.map +1 -1
- package/build/cjs/route.js.map +1 -1
- package/build/cjs/router.js +63 -34
- package/build/cjs/router.js.map +1 -1
- package/build/esm/index.js +78 -46
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +1 -1
- package/build/stats-react.json +283 -289
- package/build/types/Matches.d.ts +1 -0
- package/build/types/fileRoute.d.ts +3 -1
- package/build/types/route.d.ts +3 -1
- package/build/types/router.d.ts +2 -7
- package/build/umd/index.development.js +78 -46
- 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 +23 -15
- package/src/route.ts +3 -3
- package/src/router.ts +78 -36
package/build/types/Matches.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export interface RouteMatch<TRouteTree extends AnyRoute = AnyRoute, TRouteId ext
|
|
|
11
11
|
params: RouteById<TRouteTree, TRouteId>['types']['allParams'];
|
|
12
12
|
status: 'pending' | 'success' | 'error';
|
|
13
13
|
isFetching: boolean;
|
|
14
|
+
showPending: boolean;
|
|
14
15
|
invalid: boolean;
|
|
15
16
|
error: unknown;
|
|
16
17
|
paramsError: unknown;
|
|
@@ -19,8 +19,10 @@ export declare class FileRoute<TFilePath extends keyof FileRoutesByPath, TParent
|
|
|
19
19
|
caseSensitive?: boolean | undefined;
|
|
20
20
|
wrapInSuspense?: boolean | undefined;
|
|
21
21
|
component?: import("./route").RouteComponent<TFullSearchSchema, TAllParams, TContext, TLoaderData> | undefined;
|
|
22
|
-
errorComponent?: import("./route").ErrorRouteComponent<TFullSearchSchema, TAllParams,
|
|
22
|
+
errorComponent?: import("./route").ErrorRouteComponent<TFullSearchSchema, TAllParams, TContext> | undefined;
|
|
23
23
|
pendingComponent?: import("./route").PendingRouteComponent<TFullSearchSchema, TAllParams, TContext> | undefined;
|
|
24
|
+
pendingMs?: number | undefined;
|
|
25
|
+
pendingMinMs?: number | undefined;
|
|
24
26
|
preSearchFilters?: import("./route").SearchFilter<TFullSearchSchema, TFullSearchSchema>[] | undefined;
|
|
25
27
|
postSearchFilters?: import("./route").SearchFilter<TFullSearchSchema, TFullSearchSchema>[] | undefined;
|
|
26
28
|
onError?: ((err: any) => void) | undefined;
|
package/build/types/route.d.ts
CHANGED
|
@@ -67,8 +67,10 @@ export type UpdatableRouteOptions<TFullSearchSchema extends Record<string, any>,
|
|
|
67
67
|
caseSensitive?: boolean;
|
|
68
68
|
wrapInSuspense?: boolean;
|
|
69
69
|
component?: RouteComponent<TFullSearchSchema, TAllParams, TAllContext, TLoaderData>;
|
|
70
|
-
errorComponent?: ErrorRouteComponent<TFullSearchSchema, TAllParams,
|
|
70
|
+
errorComponent?: ErrorRouteComponent<TFullSearchSchema, TAllParams, TAllContext>;
|
|
71
71
|
pendingComponent?: PendingRouteComponent<TFullSearchSchema, TAllParams, TAllContext>;
|
|
72
|
+
pendingMs?: number;
|
|
73
|
+
pendingMinMs?: number;
|
|
72
74
|
preSearchFilters?: SearchFilter<TFullSearchSchema>[];
|
|
73
75
|
postSearchFilters?: SearchFilter<TFullSearchSchema>[];
|
|
74
76
|
onError?: (err: any) => void;
|
package/build/types/router.d.ts
CHANGED
|
@@ -40,16 +40,11 @@ export interface RouterOptions<TRouteTree extends AnyRoute, TDehydrated extends
|
|
|
40
40
|
defaultComponent?: RouteComponent<AnySearchSchema, AnyPathParams, AnyContext>;
|
|
41
41
|
defaultErrorComponent?: ErrorRouteComponent<AnySearchSchema, AnyPathParams, AnyContext>;
|
|
42
42
|
defaultPendingComponent?: PendingRouteComponent<AnySearchSchema, AnyPathParams, AnyContext>;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
defaultPreloadMaxAge?: number;
|
|
43
|
+
defaultPendingMs?: number;
|
|
44
|
+
defaultPendingMinMs?: number;
|
|
46
45
|
caseSensitive?: boolean;
|
|
47
46
|
routeTree?: TRouteTree;
|
|
48
47
|
basepath?: string;
|
|
49
|
-
createRoute?: (opts: {
|
|
50
|
-
route: AnyRoute;
|
|
51
|
-
router: AnyRouter;
|
|
52
|
-
}) => void;
|
|
53
48
|
context?: TRouteTree['types']['routerContext'];
|
|
54
49
|
routeMasks?: RouteMask<TRouteTree>[];
|
|
55
50
|
unmaskOnReload?: boolean;
|
|
@@ -978,8 +978,14 @@
|
|
|
978
978
|
const route = routesById[routeId];
|
|
979
979
|
const locationKey = useRouterState().location.state?.key;
|
|
980
980
|
const PendingComponent = route.options.pendingComponent ?? options.defaultPendingComponent;
|
|
981
|
+
const pendingElement = PendingComponent ? /*#__PURE__*/React__namespace.createElement(PendingComponent, {
|
|
982
|
+
useMatch: route.useMatch,
|
|
983
|
+
useRouteContext: route.useRouteContext,
|
|
984
|
+
useSearch: route.useSearch,
|
|
985
|
+
useParams: route.useParams
|
|
986
|
+
}) : undefined;
|
|
981
987
|
const routeErrorComponent = route.options.errorComponent ?? options.defaultErrorComponent ?? ErrorComponent;
|
|
982
|
-
const ResolvedSuspenseBoundary = route.options.wrapInSuspense ??
|
|
988
|
+
const ResolvedSuspenseBoundary = route.options.wrapInSuspense ?? pendingElement ? React__namespace.Suspense : SafeFragment;
|
|
983
989
|
const errorComponent = routeErrorComponent ? React__namespace.useCallback(props => {
|
|
984
990
|
return /*#__PURE__*/React__namespace.createElement(routeErrorComponent, {
|
|
985
991
|
...props,
|
|
@@ -993,12 +999,7 @@
|
|
|
993
999
|
return /*#__PURE__*/React__namespace.createElement(matchesContext.Provider, {
|
|
994
1000
|
value: matches
|
|
995
1001
|
}, /*#__PURE__*/React__namespace.createElement(ResolvedSuspenseBoundary, {
|
|
996
|
-
fallback:
|
|
997
|
-
useMatch: route.useMatch,
|
|
998
|
-
useRouteContext: route.useRouteContext,
|
|
999
|
-
useSearch: route.useSearch,
|
|
1000
|
-
useParams: route.useParams
|
|
1001
|
-
})
|
|
1002
|
+
fallback: pendingElement
|
|
1002
1003
|
}, /*#__PURE__*/React__namespace.createElement(ResolvedCatchBoundary, {
|
|
1003
1004
|
resetKey: locationKey,
|
|
1004
1005
|
errorComponent: errorComponent,
|
|
@@ -1006,24 +1007,26 @@
|
|
|
1006
1007
|
warning(false, `Error in route match: ${match.id}`);
|
|
1007
1008
|
}
|
|
1008
1009
|
}, /*#__PURE__*/React__namespace.createElement(MatchInner, {
|
|
1009
|
-
match: match
|
|
1010
|
+
match: match,
|
|
1011
|
+
pendingElement: pendingElement
|
|
1010
1012
|
}))));
|
|
1011
1013
|
}
|
|
1012
1014
|
function MatchInner({
|
|
1013
|
-
match
|
|
1015
|
+
match,
|
|
1016
|
+
pendingElement
|
|
1014
1017
|
}) {
|
|
1015
1018
|
const {
|
|
1016
1019
|
options,
|
|
1017
1020
|
routesById
|
|
1018
1021
|
} = useRouter();
|
|
1019
1022
|
const route = routesById[match.routeId];
|
|
1020
|
-
if (match.id.split('/').length === 4) {
|
|
1021
|
-
console.log(match.id, pick(match, ['status', 'cause', 'isFetching']));
|
|
1022
|
-
}
|
|
1023
1023
|
if (match.status === 'error') {
|
|
1024
1024
|
throw match.error;
|
|
1025
1025
|
}
|
|
1026
1026
|
if (match.status === 'pending') {
|
|
1027
|
+
if (match.showPending) {
|
|
1028
|
+
return pendingElement || null;
|
|
1029
|
+
}
|
|
1027
1030
|
throw match.loadPromise;
|
|
1028
1031
|
}
|
|
1029
1032
|
if (match.status === 'success') {
|
|
@@ -1566,6 +1569,8 @@
|
|
|
1566
1569
|
constructor(options) {
|
|
1567
1570
|
this.updateOptions({
|
|
1568
1571
|
defaultPreloadDelay: 50,
|
|
1572
|
+
defaultPendingMs: 1000,
|
|
1573
|
+
defaultPendingMinMs: 500,
|
|
1569
1574
|
context: undefined,
|
|
1570
1575
|
...options,
|
|
1571
1576
|
stringifySearch: options?.stringifySearch ?? defaultStringifySearch,
|
|
@@ -1842,6 +1847,7 @@
|
|
|
1842
1847
|
search: {},
|
|
1843
1848
|
searchError: undefined,
|
|
1844
1849
|
status: hasLoaders ? 'pending' : 'success',
|
|
1850
|
+
showPending: false,
|
|
1845
1851
|
isFetching: false,
|
|
1846
1852
|
invalid: false,
|
|
1847
1853
|
error: undefined,
|
|
@@ -2147,8 +2153,10 @@
|
|
|
2147
2153
|
matches[index] = match = {
|
|
2148
2154
|
...match,
|
|
2149
2155
|
fetchedAt: Date.now(),
|
|
2150
|
-
invalid: false
|
|
2156
|
+
invalid: false,
|
|
2157
|
+
showPending: false
|
|
2151
2158
|
};
|
|
2159
|
+
const pendingPromise = new Promise(r => setTimeout(r, 1000));
|
|
2152
2160
|
if (match.isFetching) {
|
|
2153
2161
|
loadPromise = getRouteMatch(this.state, match.id)?.loadPromise;
|
|
2154
2162
|
} else {
|
|
@@ -2213,41 +2221,65 @@
|
|
|
2213
2221
|
matches: s.matches.map(d => d.id === match.id ? match : d)
|
|
2214
2222
|
}));
|
|
2215
2223
|
}
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2224
|
+
let didShowPending = false;
|
|
2225
|
+
await new Promise(async resolve => {
|
|
2226
|
+
// If the route has a pending component and a pendingMs option,
|
|
2227
|
+
// forcefully show the pending component
|
|
2228
|
+
if (!preload && (route.options.pendingComponent ?? this.options.defaultPendingComponent) && (route.options.pendingMs ?? this.options.defaultPendingMs)) {
|
|
2229
|
+
pendingPromise.then(() => {
|
|
2230
|
+
didShowPending = true;
|
|
2231
|
+
matches[index] = match = {
|
|
2232
|
+
...match,
|
|
2233
|
+
showPending: true
|
|
2234
|
+
};
|
|
2235
|
+
this.setState(s => ({
|
|
2236
|
+
...s,
|
|
2237
|
+
matches: s.matches.map(d => d.id === match.id ? match : d)
|
|
2238
|
+
}));
|
|
2239
|
+
resolve();
|
|
2240
|
+
});
|
|
2241
|
+
}
|
|
2231
2242
|
try {
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
if (
|
|
2243
|
+
const loaderData = await loadPromise;
|
|
2244
|
+
if (latestPromise = checkLatest()) return await latestPromise;
|
|
2245
|
+
const pendingMinMs = route.options.pendingMinMs ?? this.options.defaultPendingMinMs;
|
|
2246
|
+
if (didShowPending && pendingMinMs) {
|
|
2247
|
+
await new Promise(r => setTimeout(r, pendingMinMs));
|
|
2248
|
+
}
|
|
2249
|
+
matches[index] = match = {
|
|
2250
|
+
...match,
|
|
2251
|
+
error: undefined,
|
|
2252
|
+
status: 'success',
|
|
2253
|
+
isFetching: false,
|
|
2254
|
+
updatedAt: Date.now(),
|
|
2255
|
+
loaderData,
|
|
2256
|
+
loadPromise: undefined
|
|
2257
|
+
};
|
|
2258
|
+
} catch (error) {
|
|
2259
|
+
if (latestPromise = checkLatest()) return await latestPromise;
|
|
2260
|
+
if (handleIfRedirect(error)) return;
|
|
2261
|
+
try {
|
|
2262
|
+
route.options.onError?.(error);
|
|
2263
|
+
} catch (onErrorError) {
|
|
2264
|
+
error = onErrorError;
|
|
2265
|
+
if (handleIfRedirect(onErrorError)) return;
|
|
2266
|
+
}
|
|
2267
|
+
matches[index] = match = {
|
|
2268
|
+
...match,
|
|
2269
|
+
error,
|
|
2270
|
+
status: 'error',
|
|
2271
|
+
isFetching: false,
|
|
2272
|
+
updatedAt: Date.now()
|
|
2273
|
+
};
|
|
2236
2274
|
}
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
}
|
|
2245
|
-
if (!preload) {
|
|
2246
|
-
this.setState(s => ({
|
|
2247
|
-
...s,
|
|
2248
|
-
matches: s.matches.map(d => d.id === match.id ? match : d)
|
|
2249
|
-
}));
|
|
2250
|
-
}
|
|
2275
|
+
if (!preload) {
|
|
2276
|
+
this.setState(s => ({
|
|
2277
|
+
...s,
|
|
2278
|
+
matches: s.matches.map(d => d.id === match.id ? match : d)
|
|
2279
|
+
}));
|
|
2280
|
+
}
|
|
2281
|
+
resolve();
|
|
2282
|
+
});
|
|
2251
2283
|
})());
|
|
2252
2284
|
});
|
|
2253
2285
|
await Promise.all(matchPromises);
|