@tanstack/react-router 0.0.1-beta.165 → 0.0.1-beta.167
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/deferred.js +45 -0
- package/build/cjs/deferred.js.map +1 -0
- package/build/cjs/index.js +15 -6
- package/build/cjs/index.js.map +1 -1
- package/build/esm/index.js +39 -8
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +1 -1
- package/build/stats-react.json +114 -76
- package/build/types/index.d.ts +52 -4
- package/build/umd/index.development.js +100 -21
- 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 +3 -3
- package/src/deferred.tsx +40 -0
- package/src/index.tsx +118 -11
|
@@ -726,6 +726,15 @@
|
|
|
726
726
|
|
|
727
727
|
// The parse type here allows a zod schema to be passed directly to the validator
|
|
728
728
|
|
|
729
|
+
// T extends Record<PropertyKey, infer U>
|
|
730
|
+
// ? {
|
|
731
|
+
// [K in keyof T]: UseLoaderResultPromise<T[K]>
|
|
732
|
+
// }
|
|
733
|
+
// : UseLoaderResultPromise<T>
|
|
734
|
+
|
|
735
|
+
// export type UseLoaderResultPromise<T> = T extends Promise<infer U>
|
|
736
|
+
// ? StreamedPromise<U>
|
|
737
|
+
// : T
|
|
729
738
|
class Route {
|
|
730
739
|
// Set up in this.init()
|
|
731
740
|
|
|
@@ -988,7 +997,7 @@
|
|
|
988
997
|
} = this.options;
|
|
989
998
|
this.basepath = `/${trimPath(basepath ?? '') ?? ''}`;
|
|
990
999
|
if (routeTree && routeTree !== this.routeTree) {
|
|
991
|
-
this.#
|
|
1000
|
+
this.#processRoutes(routeTree);
|
|
992
1001
|
}
|
|
993
1002
|
return this;
|
|
994
1003
|
};
|
|
@@ -1224,8 +1233,8 @@
|
|
|
1224
1233
|
params: routeParams,
|
|
1225
1234
|
pathname: joinPaths([this.basepath, interpolatedPath]),
|
|
1226
1235
|
updatedAt: Date.now(),
|
|
1227
|
-
invalidAt:
|
|
1228
|
-
preloadInvalidAt:
|
|
1236
|
+
invalidAt: 9999999999999,
|
|
1237
|
+
preloadInvalidAt: 9999999999999,
|
|
1229
1238
|
routeSearch: {},
|
|
1230
1239
|
search: {},
|
|
1231
1240
|
status: hasLoaders ? 'pending' : 'success',
|
|
@@ -1639,7 +1648,9 @@
|
|
|
1639
1648
|
};
|
|
1640
1649
|
dehydrate = () => {
|
|
1641
1650
|
return {
|
|
1642
|
-
state:
|
|
1651
|
+
state: {
|
|
1652
|
+
dehydratedMatches: this.state.matches.map(d => pick(d, ['fetchedAt', 'invalid', 'invalidAt', 'id', 'loaderData', 'status', 'updatedAt']))
|
|
1653
|
+
}
|
|
1643
1654
|
};
|
|
1644
1655
|
};
|
|
1645
1656
|
hydrate = async __do_not_use_server_ctx => {
|
|
@@ -1652,16 +1663,27 @@
|
|
|
1652
1663
|
const ctx = _ctx;
|
|
1653
1664
|
this.dehydratedData = ctx.payload;
|
|
1654
1665
|
this.options.hydrate?.(ctx.payload);
|
|
1655
|
-
const
|
|
1666
|
+
const {
|
|
1667
|
+
dehydratedMatches
|
|
1668
|
+
} = ctx.router.state;
|
|
1669
|
+
let matches = this.matchRoutes(this.state.location.pathname, this.state.location.search).map(match => {
|
|
1670
|
+
const dehydratedMatch = dehydratedMatches.find(d => d.id === match.id);
|
|
1671
|
+
invariant(dehydratedMatch, `Could not find a client-side match for dehydrated match with id: ${match.id}!`);
|
|
1672
|
+
if (dehydratedMatch) {
|
|
1673
|
+
return {
|
|
1674
|
+
...match,
|
|
1675
|
+
...dehydratedMatch
|
|
1676
|
+
};
|
|
1677
|
+
}
|
|
1678
|
+
return match;
|
|
1679
|
+
});
|
|
1656
1680
|
this.__store.setState(s => {
|
|
1657
1681
|
return {
|
|
1658
1682
|
...s,
|
|
1659
|
-
|
|
1660
|
-
|
|
1683
|
+
matches,
|
|
1684
|
+
matchesById: this.#mergeMatches(s.matchesById, matches)
|
|
1661
1685
|
};
|
|
1662
1686
|
});
|
|
1663
|
-
await this.load();
|
|
1664
|
-
return;
|
|
1665
1687
|
};
|
|
1666
1688
|
injectedHtml = [];
|
|
1667
1689
|
injectHtml = async html => {
|
|
@@ -1674,10 +1696,10 @@
|
|
|
1674
1696
|
const id = `__TSR_DEHYDRATED__${strKey}`;
|
|
1675
1697
|
const data = typeof getData === 'function' ? await getData() : getData;
|
|
1676
1698
|
return `<script id='${id}' suppressHydrationWarning>window["__TSR_DEHYDRATED__${escapeJSON(strKey)}"] = ${JSON.stringify(data)}
|
|
1677
|
-
;(() => {
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
})()
|
|
1699
|
+
// ;(() => {
|
|
1700
|
+
// var el = document.getElementById('${id}')
|
|
1701
|
+
// el.parentElement.removeChild(el)
|
|
1702
|
+
// })()
|
|
1681
1703
|
</script>`;
|
|
1682
1704
|
});
|
|
1683
1705
|
return () => this.hydrateData(key);
|
|
@@ -1698,7 +1720,7 @@
|
|
|
1698
1720
|
// ?.__promisesByKey[key]?.resolve(value)
|
|
1699
1721
|
// }
|
|
1700
1722
|
|
|
1701
|
-
#
|
|
1723
|
+
#processRoutes = routeTree => {
|
|
1702
1724
|
this.routeTree = routeTree;
|
|
1703
1725
|
this.routesById = {};
|
|
1704
1726
|
this.routesByPath = {};
|
|
@@ -1890,7 +1912,7 @@
|
|
|
1890
1912
|
const route = this.getRoute(match.routeId);
|
|
1891
1913
|
const updatedAt = opts?.updatedAt ?? Date.now();
|
|
1892
1914
|
const preloadInvalidAt = updatedAt + (opts?.maxAge ?? route.options.preloadMaxAge ?? this.options.defaultPreloadMaxAge ?? 5000);
|
|
1893
|
-
const invalidAt = updatedAt + (opts?.maxAge ?? route.options.maxAge ?? this.options.defaultMaxAge ??
|
|
1915
|
+
const invalidAt = updatedAt + (opts?.maxAge ?? route.options.maxAge ?? this.options.defaultMaxAge ?? 9999999999999);
|
|
1894
1916
|
this.setRouteMatch(id, s => ({
|
|
1895
1917
|
...s,
|
|
1896
1918
|
error: undefined,
|
|
@@ -2110,6 +2132,28 @@
|
|
|
2110
2132
|
}
|
|
2111
2133
|
}
|
|
2112
2134
|
|
|
2135
|
+
function defer(_promise) {
|
|
2136
|
+
const promise = _promise;
|
|
2137
|
+
if (!promise.__deferredState) {
|
|
2138
|
+
promise.__deferredState = {
|
|
2139
|
+
uid: Math.random().toString(36).slice(2),
|
|
2140
|
+
status: 'pending'
|
|
2141
|
+
};
|
|
2142
|
+
const state = promise.__deferredState;
|
|
2143
|
+
promise.then(data => {
|
|
2144
|
+
state.status = 'success';
|
|
2145
|
+
state.data = data;
|
|
2146
|
+
}).catch(error => {
|
|
2147
|
+
state.status = 'error';
|
|
2148
|
+
state.error = error;
|
|
2149
|
+
});
|
|
2150
|
+
}
|
|
2151
|
+
return promise;
|
|
2152
|
+
}
|
|
2153
|
+
function isDehydratedDeferred(obj) {
|
|
2154
|
+
return typeof obj === 'object' && obj !== null && !(obj instanceof Promise) && !obj.then && '__deferredState' in obj;
|
|
2155
|
+
}
|
|
2156
|
+
|
|
2113
2157
|
const useLayoutEffect = typeof window !== 'undefined' ? React__namespace.useLayoutEffect : React__namespace.useEffect;
|
|
2114
2158
|
function useScrollRestoration(options) {
|
|
2115
2159
|
const router = useRouter();
|
|
@@ -2125,6 +2169,31 @@
|
|
|
2125
2169
|
return null;
|
|
2126
2170
|
}
|
|
2127
2171
|
|
|
2172
|
+
function useDeferred({
|
|
2173
|
+
promise
|
|
2174
|
+
}) {
|
|
2175
|
+
const router = useRouter();
|
|
2176
|
+
let state = promise.__deferredState;
|
|
2177
|
+
const key = `__TSR__DEFERRED__${state.uid}`;
|
|
2178
|
+
if (isDehydratedDeferred(promise)) {
|
|
2179
|
+
state = router.hydrateData(key);
|
|
2180
|
+
promise = Promise.resolve(state.data);
|
|
2181
|
+
promise.__deferredState = state;
|
|
2182
|
+
}
|
|
2183
|
+
if (state.status === 'pending') {
|
|
2184
|
+
throw promise;
|
|
2185
|
+
}
|
|
2186
|
+
if (state.status === 'error') {
|
|
2187
|
+
throw state.error;
|
|
2188
|
+
}
|
|
2189
|
+
router.dehydrateData(key, state);
|
|
2190
|
+
return [state.data];
|
|
2191
|
+
}
|
|
2192
|
+
function Deferred(props) {
|
|
2193
|
+
const awaited = useDeferred(props);
|
|
2194
|
+
return props.children(...awaited);
|
|
2195
|
+
}
|
|
2196
|
+
|
|
2128
2197
|
Route.__onInit = route => {
|
|
2129
2198
|
Object.assign(route, {
|
|
2130
2199
|
useMatch: (opts = {}) => {
|
|
@@ -2319,11 +2388,9 @@
|
|
|
2319
2388
|
return unsub;
|
|
2320
2389
|
}, [router]);
|
|
2321
2390
|
const Wrap = router.options.Wrap || React__namespace.Fragment;
|
|
2322
|
-
return /*#__PURE__*/React__namespace.createElement(React__namespace.
|
|
2323
|
-
fallback: null
|
|
2324
|
-
}, /*#__PURE__*/React__namespace.createElement(Wrap, null, /*#__PURE__*/React__namespace.createElement(routerContext.Provider, {
|
|
2391
|
+
return /*#__PURE__*/React__namespace.createElement(Wrap, null, /*#__PURE__*/React__namespace.createElement(routerContext.Provider, {
|
|
2325
2392
|
value: router
|
|
2326
|
-
}, /*#__PURE__*/React__namespace.createElement(Matches, null)))
|
|
2393
|
+
}, /*#__PURE__*/React__namespace.createElement(Matches, null)));
|
|
2327
2394
|
}
|
|
2328
2395
|
function Matches() {
|
|
2329
2396
|
const router = useRouter();
|
|
@@ -2343,6 +2410,7 @@
|
|
|
2343
2410
|
value: [undefined, ...matchIds]
|
|
2344
2411
|
}, /*#__PURE__*/React__namespace.createElement(CatchBoundary, {
|
|
2345
2412
|
errorComponent: ErrorComponent,
|
|
2413
|
+
route: router.getRoute(rootRouteId),
|
|
2346
2414
|
onCatch: () => {
|
|
2347
2415
|
warning(false, `Error in router! Consider setting an 'errorComponent' in your RootRoute! 👍`);
|
|
2348
2416
|
}
|
|
@@ -2476,7 +2544,6 @@
|
|
|
2476
2544
|
value: matchIds
|
|
2477
2545
|
}, /*#__PURE__*/React__namespace.createElement(ResolvedSuspenseBoundary, {
|
|
2478
2546
|
fallback: /*#__PURE__*/React__namespace.createElement(PendingComponent, {
|
|
2479
|
-
useLoader: route.useLoader,
|
|
2480
2547
|
useMatch: route.useMatch,
|
|
2481
2548
|
useContext: route.useContext,
|
|
2482
2549
|
useRouteContext: route.useRouteContext,
|
|
@@ -2486,6 +2553,7 @@
|
|
|
2486
2553
|
}, /*#__PURE__*/React__namespace.createElement(ResolvedCatchBoundary, {
|
|
2487
2554
|
key: route.id,
|
|
2488
2555
|
errorComponent: errorComponent,
|
|
2556
|
+
route: route,
|
|
2489
2557
|
onCatch: () => {
|
|
2490
2558
|
warning(false, `Error in route match: ${matchId}`);
|
|
2491
2559
|
}
|
|
@@ -2602,7 +2670,14 @@
|
|
|
2602
2670
|
// props.reset()
|
|
2603
2671
|
}, [props.errorState.error]);
|
|
2604
2672
|
if (props.errorState.error && activeErrorState.error) {
|
|
2605
|
-
return /*#__PURE__*/React__namespace.createElement(errorComponent,
|
|
2673
|
+
return /*#__PURE__*/React__namespace.createElement(errorComponent, {
|
|
2674
|
+
...activeErrorState,
|
|
2675
|
+
useMatch: props.route.useMatch,
|
|
2676
|
+
useContext: props.route.useContext,
|
|
2677
|
+
useRouteContext: props.route.useRouteContext,
|
|
2678
|
+
useSearch: props.route.useSearch,
|
|
2679
|
+
useParams: props.route.useParams
|
|
2680
|
+
});
|
|
2606
2681
|
}
|
|
2607
2682
|
return props.children;
|
|
2608
2683
|
}
|
|
@@ -2691,6 +2766,7 @@
|
|
|
2691
2766
|
}
|
|
2692
2767
|
|
|
2693
2768
|
exports.Block = Block;
|
|
2769
|
+
exports.Deferred = Deferred;
|
|
2694
2770
|
exports.ErrorComponent = ErrorComponent;
|
|
2695
2771
|
exports.FileRoute = FileRoute;
|
|
2696
2772
|
exports.Link = Link;
|
|
@@ -2713,10 +2789,12 @@
|
|
|
2713
2789
|
exports.decode = decode;
|
|
2714
2790
|
exports.defaultParseSearch = defaultParseSearch;
|
|
2715
2791
|
exports.defaultStringifySearch = defaultStringifySearch;
|
|
2792
|
+
exports.defer = defer;
|
|
2716
2793
|
exports.encode = encode;
|
|
2717
2794
|
exports.functionalUpdate = functionalUpdate;
|
|
2718
2795
|
exports.interpolatePath = interpolatePath;
|
|
2719
2796
|
exports.invariant = invariant;
|
|
2797
|
+
exports.isDehydratedDeferred = isDehydratedDeferred;
|
|
2720
2798
|
exports.isPlainObject = isPlainObject;
|
|
2721
2799
|
exports.isRedirect = isRedirect;
|
|
2722
2800
|
exports.joinPaths = joinPaths;
|
|
@@ -2742,6 +2820,7 @@
|
|
|
2742
2820
|
exports.trimPathLeft = trimPathLeft;
|
|
2743
2821
|
exports.trimPathRight = trimPathRight;
|
|
2744
2822
|
exports.useBlocker = useBlocker;
|
|
2823
|
+
exports.useDeferred = useDeferred;
|
|
2745
2824
|
exports.useDehydrate = useDehydrate;
|
|
2746
2825
|
exports.useHydrate = useHydrate;
|
|
2747
2826
|
exports.useInjectHtml = useInjectHtml;
|