@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.
@@ -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 opts => {
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 = !!(opts?.next && prevLocation.href !== opts.next.href);
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: opts?.next ?? state.location,
1620
+ to: next ?? state.location,
1614
1621
  pathChanged: pathDidChange
1615
1622
  });
1616
- if (opts?.next) {
1617
- // Ingest the new location
1618
- setState(s => ({
1619
- ...s,
1620
- location: opts.next
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
- const matches = matchRoutes(state.location.pathname, state.location.search, {
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: state.location,
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
- setState(s => ({
1826
- ...s,
1827
- location: latestLocationRef.current
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
- safeLoad();
1851
- }
1852
- React__namespace.useLayoutEffect(() => {
1853
- if (state.resolvedLocation !== state.location) {
1854
- safeLoad();
1853
+ try {
1854
+ load();
1855
+ } catch (err) {
1856
+ console.error(err);
1855
1857
  }
1856
- }, [state.location]);
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 value = React__namespace.useContext(routerContext);
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
  }