@tanstack/react-router 0.0.1-beta.228 → 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 -9
- 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 -43
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +1 -1
- package/build/stats-react.json +283 -283
- 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 -43
- 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 -11
- 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,11 +1007,13 @@
|
|
|
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,
|
|
@@ -1021,6 +1024,9 @@
|
|
|
1021
1024
|
throw match.error;
|
|
1022
1025
|
}
|
|
1023
1026
|
if (match.status === 'pending') {
|
|
1027
|
+
if (match.showPending) {
|
|
1028
|
+
return pendingElement || null;
|
|
1029
|
+
}
|
|
1024
1030
|
throw match.loadPromise;
|
|
1025
1031
|
}
|
|
1026
1032
|
if (match.status === 'success') {
|
|
@@ -1563,6 +1569,8 @@
|
|
|
1563
1569
|
constructor(options) {
|
|
1564
1570
|
this.updateOptions({
|
|
1565
1571
|
defaultPreloadDelay: 50,
|
|
1572
|
+
defaultPendingMs: 1000,
|
|
1573
|
+
defaultPendingMinMs: 500,
|
|
1566
1574
|
context: undefined,
|
|
1567
1575
|
...options,
|
|
1568
1576
|
stringifySearch: options?.stringifySearch ?? defaultStringifySearch,
|
|
@@ -1839,6 +1847,7 @@
|
|
|
1839
1847
|
search: {},
|
|
1840
1848
|
searchError: undefined,
|
|
1841
1849
|
status: hasLoaders ? 'pending' : 'success',
|
|
1850
|
+
showPending: false,
|
|
1842
1851
|
isFetching: false,
|
|
1843
1852
|
invalid: false,
|
|
1844
1853
|
error: undefined,
|
|
@@ -2144,8 +2153,10 @@
|
|
|
2144
2153
|
matches[index] = match = {
|
|
2145
2154
|
...match,
|
|
2146
2155
|
fetchedAt: Date.now(),
|
|
2147
|
-
invalid: false
|
|
2156
|
+
invalid: false,
|
|
2157
|
+
showPending: false
|
|
2148
2158
|
};
|
|
2159
|
+
const pendingPromise = new Promise(r => setTimeout(r, 1000));
|
|
2149
2160
|
if (match.isFetching) {
|
|
2150
2161
|
loadPromise = getRouteMatch(this.state, match.id)?.loadPromise;
|
|
2151
2162
|
} else {
|
|
@@ -2210,41 +2221,65 @@
|
|
|
2210
2221
|
matches: s.matches.map(d => d.id === match.id ? match : d)
|
|
2211
2222
|
}));
|
|
2212
2223
|
}
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
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
|
+
}
|
|
2228
2242
|
try {
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
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
|
+
};
|
|
2233
2274
|
}
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
}
|
|
2242
|
-
if (!preload) {
|
|
2243
|
-
this.setState(s => ({
|
|
2244
|
-
...s,
|
|
2245
|
-
matches: s.matches.map(d => d.id === match.id ? match : d)
|
|
2246
|
-
}));
|
|
2247
|
-
}
|
|
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
|
+
});
|
|
2248
2283
|
})());
|
|
2249
2284
|
});
|
|
2250
2285
|
await Promise.all(matchPromises);
|