@tanstack/react-router 0.0.1-beta.206 → 0.0.1-beta.208

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.
@@ -671,6 +671,9 @@ function isRedirect(obj) {
671
671
 
672
672
  const preloadWarning = 'Error preloading route! ☝️';
673
673
  const routerContext = /*#__PURE__*/React.createContext(null);
674
+ if (typeof document !== 'undefined') {
675
+ window.__TSR_ROUTER_CONTEXT__ = routerContext;
676
+ }
674
677
  function getInitialRouterState(location) {
675
678
  return {
676
679
  status: 'idle',
@@ -698,6 +701,10 @@ function RouterProvider({
698
701
  const tempLocationKeyRef = React.useRef(`${Math.round(Math.random() * 10000000)}`);
699
702
  const resetNextScrollRef = React.useRef(false);
700
703
  const navigateTimeoutRef = React.useRef(null);
704
+ const latestLoadPromiseRef = React.useRef(Promise.resolve());
705
+ const checkLatest = promise => {
706
+ return latestLoadPromiseRef.current !== promise ? latestLoadPromiseRef.current : undefined;
707
+ };
701
708
  const parseLocation = useStableCallback(previousLocation => {
702
709
  const parse = ({
703
710
  pathname,
@@ -821,7 +828,6 @@ function RouterProvider({
821
828
  d.child.rank = i;
822
829
  return d.child;
823
830
  }), [routesByPath]);
824
- const latestLoadPromiseRef = React.useRef(Promise.resolve());
825
831
  const matchRoutes = useStableCallback((pathname, locationSearch, opts) => {
826
832
  let routeParams = {};
827
833
  let foundRoute = flatRoutes.find(route => {
@@ -1120,9 +1126,11 @@ function RouterProvider({
1120
1126
  });
1121
1127
  });
1122
1128
  const loadMatches = useStableCallback(async ({
1129
+ checkLatest,
1123
1130
  matches,
1124
1131
  preload
1125
1132
  }) => {
1133
+ let latestPromise;
1126
1134
  let firstBadMatchIndex;
1127
1135
 
1128
1136
  // Check each match middleware to see if the route can be accessed
@@ -1165,7 +1173,12 @@ function RouterProvider({
1165
1173
  params: match.params,
1166
1174
  preload: !!preload,
1167
1175
  meta: parentMeta,
1168
- location: state.location // TODO: This might need to be latestLocationRef.current...?
1176
+ location: state.location,
1177
+ // TODO: This might need to be latestLocationRef.current...?
1178
+ navigate: opts => navigate({
1179
+ ...opts,
1180
+ from: match.pathname
1181
+ })
1169
1182
  })) ?? {};
1170
1183
  const meta = {
1171
1184
  ...parentMeta,
@@ -1183,7 +1196,7 @@ function RouterProvider({
1183
1196
  } catch (err) {
1184
1197
  if (isRedirect(err)) {
1185
1198
  if (!preload) navigate(err);
1186
- return;
1199
+ return matches;
1187
1200
  }
1188
1201
  throw err;
1189
1202
  }
@@ -1196,11 +1209,6 @@ function RouterProvider({
1196
1209
  if (match.isFetching) {
1197
1210
  return getRouteMatch(state, match.id)?.loadPromise;
1198
1211
  }
1199
- const fetchedAt = Date.now();
1200
- const checkLatest = () => {
1201
- const latest = getRouteMatch(state, match.id);
1202
- return latest && latest.fetchedAt !== fetchedAt ? latest.loadPromise : undefined;
1203
- };
1204
1212
  const handleIfRedirect = err => {
1205
1213
  if (isRedirect(err)) {
1206
1214
  if (!preload) {
@@ -1211,7 +1219,6 @@ function RouterProvider({
1211
1219
  return false;
1212
1220
  };
1213
1221
  const load = async () => {
1214
- let latestPromise;
1215
1222
  try {
1216
1223
  const componentsPromise = Promise.all(componentTypes.map(async type => {
1217
1224
  const component = route.options[type];
@@ -1225,7 +1232,12 @@ function RouterProvider({
1225
1232
  preload: !!preload,
1226
1233
  parentMatchPromise,
1227
1234
  abortController: match.abortController,
1228
- meta: match.meta
1235
+ meta: match.meta,
1236
+ location: state.location,
1237
+ navigate: opts => navigate({
1238
+ ...opts,
1239
+ from: match.pathname
1240
+ })
1229
1241
  });
1230
1242
  await Promise.all([componentsPromise, loaderPromise]);
1231
1243
  if (latestPromise = checkLatest()) return await latestPromise;
@@ -1253,12 +1265,18 @@ function RouterProvider({
1253
1265
  updatedAt: Date.now()
1254
1266
  };
1255
1267
  }
1268
+ if (!preload) {
1269
+ setState(s => ({
1270
+ ...s,
1271
+ matches: s.matches.map(d => d.id === match.id ? match : d)
1272
+ }));
1273
+ }
1256
1274
  };
1257
1275
  let loadPromise;
1258
1276
  matches[index] = match = {
1259
1277
  ...match,
1260
1278
  isFetching: true,
1261
- fetchedAt,
1279
+ fetchedAt: Date.now(),
1262
1280
  invalid: false
1263
1281
  };
1264
1282
  loadPromise = load();
@@ -1270,35 +1288,32 @@ function RouterProvider({
1270
1288
  })());
1271
1289
  });
1272
1290
  await Promise.all(matchPromises);
1291
+ return matches;
1273
1292
  });
1274
- const load = useStableCallback(async opts => {
1293
+ const load = useStableCallback(async () => {
1275
1294
  const promise = new Promise(async (resolve, reject) => {
1295
+ const next = latestLocationRef.current;
1276
1296
  const prevLocation = state.resolvedLocation;
1277
- const pathDidChange = !!(opts?.next && prevLocation.href !== opts.next.href);
1297
+ const pathDidChange = !!(next && prevLocation.href !== next.href);
1278
1298
  let latestPromise;
1279
- const checkLatest = () => {
1280
- return latestLoadPromiseRef.current !== promise ? latestLoadPromiseRef.current : undefined;
1281
- };
1282
1299
 
1283
1300
  // Cancel any pending matches
1284
1301
  cancelMatches(state);
1285
1302
  router.emit({
1286
1303
  type: 'onBeforeLoad',
1287
1304
  from: prevLocation,
1288
- to: opts?.next ?? state.location,
1305
+ to: next ?? state.location,
1289
1306
  pathChanged: pathDidChange
1290
1307
  });
1291
- if (opts?.next) {
1292
- // Ingest the new location
1293
- setState(s => ({
1294
- ...s,
1295
- location: opts.next
1296
- }));
1297
- }
1308
+
1309
+ // Ingest the new location
1310
+ setState(s => ({
1311
+ ...s,
1312
+ location: next
1313
+ }));
1298
1314
 
1299
1315
  // Match the routes
1300
- const matches = matchRoutes(state.location.pathname, state.location.search, {
1301
- throwOnError: opts?.throwOnError,
1316
+ let matches = matchRoutes(next.pathname, next.search, {
1302
1317
  debug: true
1303
1318
  });
1304
1319
  setState(s => ({
@@ -1307,10 +1322,11 @@ function RouterProvider({
1307
1322
  matches
1308
1323
  }));
1309
1324
  try {
1310
- // Load the matches
1311
1325
  try {
1326
+ // Load the matches
1312
1327
  await loadMatches({
1313
- matches
1328
+ matches,
1329
+ checkLatest: () => checkLatest(promise)
1314
1330
  });
1315
1331
  } catch (err) {
1316
1332
  // swallow this error, since we'll display the
@@ -1318,7 +1334,7 @@ function RouterProvider({
1318
1334
  }
1319
1335
 
1320
1336
  // Only apply the latest transition
1321
- if (latestPromise = checkLatest()) {
1337
+ if (latestPromise = checkLatest(promise)) {
1322
1338
  return latestPromise;
1323
1339
  }
1324
1340
 
@@ -1355,13 +1371,13 @@ function RouterProvider({
1355
1371
  router.emit({
1356
1372
  type: 'onLoad',
1357
1373
  from: prevLocation,
1358
- to: state.location,
1374
+ to: next,
1359
1375
  pathChanged: pathDidChange
1360
1376
  });
1361
1377
  resolve();
1362
1378
  } catch (err) {
1363
1379
  // Only apply the latest transition
1364
- if (latestPromise = checkLatest()) {
1380
+ if (latestPromise = checkLatest(promise)) {
1365
1381
  return latestPromise;
1366
1382
  }
1367
1383
  reject(err);
@@ -1370,13 +1386,6 @@ function RouterProvider({
1370
1386
  latestLoadPromiseRef.current = promise;
1371
1387
  return latestLoadPromiseRef.current;
1372
1388
  });
1373
- const safeLoad = React.useCallback(async () => {
1374
- try {
1375
- return load();
1376
- } catch (err) {
1377
- // Don't do anything
1378
- }
1379
- }, []);
1380
1389
  const preloadRoute = useStableCallback(async (navigateOpts = state.location) => {
1381
1390
  let next = buildLocation(navigateOpts);
1382
1391
  let matches = matchRoutes(next.pathname, next.search, {
@@ -1384,7 +1393,8 @@ function RouterProvider({
1384
1393
  });
1385
1394
  await loadMatches({
1386
1395
  matches,
1387
- preload: true
1396
+ preload: true,
1397
+ checkLatest: () => undefined
1388
1398
  });
1389
1399
  return [last(matches), matches];
1390
1400
  });
@@ -1497,10 +1507,13 @@ function RouterProvider({
1497
1507
  const unsub = history.subscribe(() => {
1498
1508
  latestLocationRef.current = parseLocation(latestLocationRef.current);
1499
1509
  React.startTransition(() => {
1500
- setState(s => ({
1501
- ...s,
1502
- location: latestLocationRef.current
1503
- }));
1510
+ if (state.location !== latestLocationRef.current) {
1511
+ try {
1512
+ load();
1513
+ } catch (err) {
1514
+ console.error(err);
1515
+ }
1516
+ }
1504
1517
  });
1505
1518
  });
1506
1519
  const nextLocation = buildLocation({
@@ -1522,13 +1535,12 @@ function RouterProvider({
1522
1535
  const initialLoad = React.useRef(true);
1523
1536
  if (initialLoad.current) {
1524
1537
  initialLoad.current = false;
1525
- safeLoad();
1526
- }
1527
- React.useLayoutEffect(() => {
1528
- if (state.resolvedLocation !== state.location) {
1529
- safeLoad();
1538
+ try {
1539
+ load();
1540
+ } catch (err) {
1541
+ console.error(err);
1530
1542
  }
1531
- }, [state.location]);
1543
+ }
1532
1544
  React.useMemo(() => [...state.matches, ...state.pendingMatches].some(d => d.isFetching), [state.matches, state.pendingMatches]);
1533
1545
  const matchRoute = useStableCallback((state, location, opts) => {
1534
1546
  location = {
@@ -1733,7 +1745,8 @@ function Navigate(props) {
1733
1745
  }
1734
1746
  const matchesContext = /*#__PURE__*/React.createContext(null);
1735
1747
  function useRouter() {
1736
- const value = React.useContext(routerContext);
1748
+ const resolvedContext = window.__TSR_ROUTER_CONTEXT__ || routerContext;
1749
+ const value = React.useContext(resolvedContext);
1737
1750
  warning(value, 'useRouter must be used inside a <RouterProvider> component!');
1738
1751
  return value;
1739
1752
  }
@@ -1811,6 +1824,9 @@ function useNavigate(defaultOpts) {
1811
1824
  });
1812
1825
  }, []);
1813
1826
  }
1827
+ function typedNavigate(navigate) {
1828
+ return navigate;
1829
+ }
1814
1830
  function useMatchRoute() {
1815
1831
  const {
1816
1832
  state,
@@ -2243,5 +2259,5 @@ class FileRoute {
2243
2259
  };
2244
2260
  }
2245
2261
 
2246
- export { Block, CatchBoundary, CatchBoundaryImpl, ErrorComponent, FileRoute, Link, MatchRoute, Matches, Navigate, Outlet, PathParamError, RootRoute, Route, Router, RouterMeta, RouterProvider, SearchParamError, cleanPath, componentTypes, createRouteMask, decode, defaultParseSearch, defaultStringifySearch, encode, functionalUpdate, getInitialRouterState, getRouteMatch, interpolatePath, isPlainObject, isRedirect, isServer, joinPaths, last, lazyFn, lazyRouteComponent, matchByPath, matchPathname, matchesContext, parsePathname, parseSearchWith, partialDeepEqual, pick, redirect, replaceEqualDeep, resolvePath, rootRouteId, routerContext, shallow, stringifySearchWith, trimPath, trimPathLeft, trimPathRight, useBlocker, useLinkProps, useMatch, useMatchRoute, useMatches, useNavigate, useParams, useRouteMeta, useRouter, useRouterState, useSearch, useStableCallback };
2262
+ export { Block, CatchBoundary, CatchBoundaryImpl, ErrorComponent, FileRoute, Link, MatchRoute, Matches, Navigate, Outlet, PathParamError, RootRoute, Route, Router, RouterMeta, RouterProvider, SearchParamError, cleanPath, componentTypes, createRouteMask, decode, defaultParseSearch, defaultStringifySearch, encode, functionalUpdate, getInitialRouterState, getRouteMatch, interpolatePath, isPlainObject, isRedirect, isServer, joinPaths, last, lazyFn, lazyRouteComponent, matchByPath, matchPathname, matchesContext, parsePathname, parseSearchWith, partialDeepEqual, pick, redirect, replaceEqualDeep, resolvePath, rootRouteId, routerContext, shallow, stringifySearchWith, trimPath, trimPathLeft, trimPathRight, typedNavigate, useBlocker, useLinkProps, useMatch, useMatchRoute, useMatches, useNavigate, useParams, useRouteMeta, useRouter, useRouterState, useSearch, useStableCallback };
2247
2263
  //# sourceMappingURL=index.js.map