@tanstack/react-router 0.0.1-beta.206 → 0.0.1-beta.207
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/RouterProvider.js +49 -47
- package/build/cjs/RouterProvider.js.map +1 -1
- package/build/cjs/react.js +2 -1
- package/build/cjs/react.js.map +1 -1
- package/build/cjs/router.js.map +1 -1
- package/build/esm/index.js +51 -48
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +1 -1
- package/build/stats-react.json +167 -167
- package/build/types/router.d.ts +3 -0
- package/build/umd/index.development.js +51 -48
- 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/RouterProvider.tsx +58 -61
- package/src/react.tsx +2 -1
- package/src/router.ts +2 -0
package/build/types/router.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
1
2
|
import { RouterHistory } from '@tanstack/history';
|
|
2
3
|
import { AnySearchSchema, AnyRoute, AnyContext, AnyPathParams, RouteMask } from './route';
|
|
3
4
|
import { FullSearchSchema } from './routeInfo';
|
|
@@ -7,9 +8,11 @@ import { RouteMatch } from './RouteMatch';
|
|
|
7
8
|
import { ParsedLocation } from './location';
|
|
8
9
|
import { LocationState } from './location';
|
|
9
10
|
import { SearchSerializer, SearchParser } from './searchParams';
|
|
11
|
+
import { RouterContext } from './RouterProvider';
|
|
10
12
|
declare global {
|
|
11
13
|
interface Window {
|
|
12
14
|
__TSR_DEHYDRATED__?: HydrationCtx;
|
|
15
|
+
__TSR_ROUTER_CONTEXT__?: React.Context<RouterContext<any>>;
|
|
13
16
|
}
|
|
14
17
|
}
|
|
15
18
|
export interface Register {
|
|
@@ -996,6 +996,9 @@
|
|
|
996
996
|
|
|
997
997
|
const preloadWarning = 'Error preloading route! ☝️';
|
|
998
998
|
const routerContext = /*#__PURE__*/React__namespace.createContext(null);
|
|
999
|
+
if (typeof document !== 'undefined') {
|
|
1000
|
+
window.__TSR_ROUTER_CONTEXT__ = routerContext;
|
|
1001
|
+
}
|
|
999
1002
|
function getInitialRouterState(location) {
|
|
1000
1003
|
return {
|
|
1001
1004
|
status: 'idle',
|
|
@@ -1023,6 +1026,10 @@
|
|
|
1023
1026
|
const tempLocationKeyRef = React__namespace.useRef(`${Math.round(Math.random() * 10000000)}`);
|
|
1024
1027
|
const resetNextScrollRef = React__namespace.useRef(false);
|
|
1025
1028
|
const navigateTimeoutRef = React__namespace.useRef(null);
|
|
1029
|
+
const latestLoadPromiseRef = React__namespace.useRef(Promise.resolve());
|
|
1030
|
+
const checkLatest = promise => {
|
|
1031
|
+
return latestLoadPromiseRef.current !== promise ? latestLoadPromiseRef.current : undefined;
|
|
1032
|
+
};
|
|
1026
1033
|
const parseLocation = useStableCallback(previousLocation => {
|
|
1027
1034
|
const parse = ({
|
|
1028
1035
|
pathname,
|
|
@@ -1146,7 +1153,6 @@
|
|
|
1146
1153
|
d.child.rank = i;
|
|
1147
1154
|
return d.child;
|
|
1148
1155
|
}), [routesByPath]);
|
|
1149
|
-
const latestLoadPromiseRef = React__namespace.useRef(Promise.resolve());
|
|
1150
1156
|
const matchRoutes = useStableCallback((pathname, locationSearch, opts) => {
|
|
1151
1157
|
let routeParams = {};
|
|
1152
1158
|
let foundRoute = flatRoutes.find(route => {
|
|
@@ -1445,9 +1451,11 @@
|
|
|
1445
1451
|
});
|
|
1446
1452
|
});
|
|
1447
1453
|
const loadMatches = useStableCallback(async ({
|
|
1454
|
+
checkLatest,
|
|
1448
1455
|
matches,
|
|
1449
1456
|
preload
|
|
1450
1457
|
}) => {
|
|
1458
|
+
let latestPromise;
|
|
1451
1459
|
let firstBadMatchIndex;
|
|
1452
1460
|
|
|
1453
1461
|
// Check each match middleware to see if the route can be accessed
|
|
@@ -1508,7 +1516,7 @@
|
|
|
1508
1516
|
} catch (err) {
|
|
1509
1517
|
if (isRedirect(err)) {
|
|
1510
1518
|
if (!preload) navigate(err);
|
|
1511
|
-
return;
|
|
1519
|
+
return matches;
|
|
1512
1520
|
}
|
|
1513
1521
|
throw err;
|
|
1514
1522
|
}
|
|
@@ -1521,11 +1529,6 @@
|
|
|
1521
1529
|
if (match.isFetching) {
|
|
1522
1530
|
return getRouteMatch(state, match.id)?.loadPromise;
|
|
1523
1531
|
}
|
|
1524
|
-
const fetchedAt = Date.now();
|
|
1525
|
-
const checkLatest = () => {
|
|
1526
|
-
const latest = getRouteMatch(state, match.id);
|
|
1527
|
-
return latest && latest.fetchedAt !== fetchedAt ? latest.loadPromise : undefined;
|
|
1528
|
-
};
|
|
1529
1532
|
const handleIfRedirect = err => {
|
|
1530
1533
|
if (isRedirect(err)) {
|
|
1531
1534
|
if (!preload) {
|
|
@@ -1536,7 +1539,6 @@
|
|
|
1536
1539
|
return false;
|
|
1537
1540
|
};
|
|
1538
1541
|
const load = async () => {
|
|
1539
|
-
let latestPromise;
|
|
1540
1542
|
try {
|
|
1541
1543
|
const componentsPromise = Promise.all(componentTypes.map(async type => {
|
|
1542
1544
|
const component = route.options[type];
|
|
@@ -1578,12 +1580,18 @@
|
|
|
1578
1580
|
updatedAt: Date.now()
|
|
1579
1581
|
};
|
|
1580
1582
|
}
|
|
1583
|
+
if (!preload) {
|
|
1584
|
+
setState(s => ({
|
|
1585
|
+
...s,
|
|
1586
|
+
matches: s.matches.map(d => d.id === match.id ? match : d)
|
|
1587
|
+
}));
|
|
1588
|
+
}
|
|
1581
1589
|
};
|
|
1582
1590
|
let loadPromise;
|
|
1583
1591
|
matches[index] = match = {
|
|
1584
1592
|
...match,
|
|
1585
1593
|
isFetching: true,
|
|
1586
|
-
fetchedAt,
|
|
1594
|
+
fetchedAt: Date.now(),
|
|
1587
1595
|
invalid: false
|
|
1588
1596
|
};
|
|
1589
1597
|
loadPromise = load();
|
|
@@ -1595,35 +1603,32 @@
|
|
|
1595
1603
|
})());
|
|
1596
1604
|
});
|
|
1597
1605
|
await Promise.all(matchPromises);
|
|
1606
|
+
return matches;
|
|
1598
1607
|
});
|
|
1599
|
-
const load = useStableCallback(async
|
|
1608
|
+
const load = useStableCallback(async () => {
|
|
1600
1609
|
const promise = new Promise(async (resolve, reject) => {
|
|
1610
|
+
const next = latestLocationRef.current;
|
|
1601
1611
|
const prevLocation = state.resolvedLocation;
|
|
1602
|
-
const pathDidChange = !!(
|
|
1612
|
+
const pathDidChange = !!(next && prevLocation.href !== next.href);
|
|
1603
1613
|
let latestPromise;
|
|
1604
|
-
const checkLatest = () => {
|
|
1605
|
-
return latestLoadPromiseRef.current !== promise ? latestLoadPromiseRef.current : undefined;
|
|
1606
|
-
};
|
|
1607
1614
|
|
|
1608
1615
|
// Cancel any pending matches
|
|
1609
1616
|
cancelMatches(state);
|
|
1610
1617
|
router.emit({
|
|
1611
1618
|
type: 'onBeforeLoad',
|
|
1612
1619
|
from: prevLocation,
|
|
1613
|
-
to:
|
|
1620
|
+
to: next ?? state.location,
|
|
1614
1621
|
pathChanged: pathDidChange
|
|
1615
1622
|
});
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
}
|
|
1623
|
+
|
|
1624
|
+
// Ingest the new location
|
|
1625
|
+
setState(s => ({
|
|
1626
|
+
...s,
|
|
1627
|
+
location: next
|
|
1628
|
+
}));
|
|
1623
1629
|
|
|
1624
1630
|
// Match the routes
|
|
1625
|
-
|
|
1626
|
-
throwOnError: opts?.throwOnError,
|
|
1631
|
+
let matches = matchRoutes(next.pathname, next.search, {
|
|
1627
1632
|
debug: true
|
|
1628
1633
|
});
|
|
1629
1634
|
setState(s => ({
|
|
@@ -1632,10 +1637,11 @@
|
|
|
1632
1637
|
matches
|
|
1633
1638
|
}));
|
|
1634
1639
|
try {
|
|
1635
|
-
// Load the matches
|
|
1636
1640
|
try {
|
|
1641
|
+
// Load the matches
|
|
1637
1642
|
await loadMatches({
|
|
1638
|
-
matches
|
|
1643
|
+
matches,
|
|
1644
|
+
checkLatest: () => checkLatest(promise)
|
|
1639
1645
|
});
|
|
1640
1646
|
} catch (err) {
|
|
1641
1647
|
// swallow this error, since we'll display the
|
|
@@ -1643,7 +1649,7 @@
|
|
|
1643
1649
|
}
|
|
1644
1650
|
|
|
1645
1651
|
// Only apply the latest transition
|
|
1646
|
-
if (latestPromise = checkLatest()) {
|
|
1652
|
+
if (latestPromise = checkLatest(promise)) {
|
|
1647
1653
|
return latestPromise;
|
|
1648
1654
|
}
|
|
1649
1655
|
|
|
@@ -1680,13 +1686,13 @@
|
|
|
1680
1686
|
router.emit({
|
|
1681
1687
|
type: 'onLoad',
|
|
1682
1688
|
from: prevLocation,
|
|
1683
|
-
to:
|
|
1689
|
+
to: next,
|
|
1684
1690
|
pathChanged: pathDidChange
|
|
1685
1691
|
});
|
|
1686
1692
|
resolve();
|
|
1687
1693
|
} catch (err) {
|
|
1688
1694
|
// Only apply the latest transition
|
|
1689
|
-
if (latestPromise = checkLatest()) {
|
|
1695
|
+
if (latestPromise = checkLatest(promise)) {
|
|
1690
1696
|
return latestPromise;
|
|
1691
1697
|
}
|
|
1692
1698
|
reject(err);
|
|
@@ -1695,13 +1701,6 @@
|
|
|
1695
1701
|
latestLoadPromiseRef.current = promise;
|
|
1696
1702
|
return latestLoadPromiseRef.current;
|
|
1697
1703
|
});
|
|
1698
|
-
const safeLoad = React__namespace.useCallback(async () => {
|
|
1699
|
-
try {
|
|
1700
|
-
return load();
|
|
1701
|
-
} catch (err) {
|
|
1702
|
-
// Don't do anything
|
|
1703
|
-
}
|
|
1704
|
-
}, []);
|
|
1705
1704
|
const preloadRoute = useStableCallback(async (navigateOpts = state.location) => {
|
|
1706
1705
|
let next = buildLocation(navigateOpts);
|
|
1707
1706
|
let matches = matchRoutes(next.pathname, next.search, {
|
|
@@ -1709,7 +1708,8 @@
|
|
|
1709
1708
|
});
|
|
1710
1709
|
await loadMatches({
|
|
1711
1710
|
matches,
|
|
1712
|
-
preload: true
|
|
1711
|
+
preload: true,
|
|
1712
|
+
checkLatest: () => undefined
|
|
1713
1713
|
});
|
|
1714
1714
|
return [last(matches), matches];
|
|
1715
1715
|
});
|
|
@@ -1822,10 +1822,13 @@
|
|
|
1822
1822
|
const unsub = history.subscribe(() => {
|
|
1823
1823
|
latestLocationRef.current = parseLocation(latestLocationRef.current);
|
|
1824
1824
|
React__namespace.startTransition(() => {
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1825
|
+
if (state.location !== latestLocationRef.current) {
|
|
1826
|
+
try {
|
|
1827
|
+
load();
|
|
1828
|
+
} catch (err) {
|
|
1829
|
+
console.error(err);
|
|
1830
|
+
}
|
|
1831
|
+
}
|
|
1829
1832
|
});
|
|
1830
1833
|
});
|
|
1831
1834
|
const nextLocation = buildLocation({
|
|
@@ -1847,13 +1850,12 @@
|
|
|
1847
1850
|
const initialLoad = React__namespace.useRef(true);
|
|
1848
1851
|
if (initialLoad.current) {
|
|
1849
1852
|
initialLoad.current = false;
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
safeLoad();
|
|
1853
|
+
try {
|
|
1854
|
+
load();
|
|
1855
|
+
} catch (err) {
|
|
1856
|
+
console.error(err);
|
|
1855
1857
|
}
|
|
1856
|
-
}
|
|
1858
|
+
}
|
|
1857
1859
|
React__namespace.useMemo(() => [...state.matches, ...state.pendingMatches].some(d => d.isFetching), [state.matches, state.pendingMatches]);
|
|
1858
1860
|
const matchRoute = useStableCallback((state, location, opts) => {
|
|
1859
1861
|
location = {
|
|
@@ -2058,7 +2060,8 @@
|
|
|
2058
2060
|
}
|
|
2059
2061
|
const matchesContext = /*#__PURE__*/React__namespace.createContext(null);
|
|
2060
2062
|
function useRouter() {
|
|
2061
|
-
const
|
|
2063
|
+
const resolvedContext = window.__TSR_ROUTER_CONTEXT__ || routerContext;
|
|
2064
|
+
const value = React__namespace.useContext(resolvedContext);
|
|
2062
2065
|
warning(value, 'useRouter must be used inside a <RouterProvider> component!');
|
|
2063
2066
|
return value;
|
|
2064
2067
|
}
|