@tanstack/router-core 0.0.1-beta.11 → 0.0.1-beta.14

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.
@@ -16,47 +16,6 @@ interface FrameworkGenerics {
16
16
  }
17
17
  declare type GetFrameworkGeneric<U> = U extends keyof FrameworkGenerics ? FrameworkGenerics[U] : any;
18
18
 
19
- declare type NoInfer<T> = [T][T extends any ? 0 : never];
20
- declare type IsAny<T, Y, N> = 1 extends 0 & T ? Y : N;
21
- declare type IsAnyBoolean<T> = 1 extends 0 & T ? true : false;
22
- declare type IsKnown<T, Y, N> = unknown extends T ? N : Y;
23
- declare type PickAsRequired<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;
24
- declare type PickAsPartial<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
25
- declare type PickUnsafe<T, K> = K extends keyof T ? Pick<T, K> : never;
26
- declare type PickExtra<T, K> = Expand<{
27
- [TKey in keyof K as string extends TKey ? never : TKey extends keyof T ? never : TKey]: K[TKey];
28
- }>;
29
- declare type PickRequired<T> = {
30
- [K in keyof T as undefined extends T[K] ? never : K]: T[K];
31
- };
32
- declare type Expand<T> = T extends object ? T extends infer O ? {
33
- [K in keyof O]: O[K];
34
- } : never : T;
35
- declare type Values<O> = O[ValueKeys<O>];
36
- declare type ValueKeys<O> = Extract<keyof O, PropertyKey>;
37
- declare type DeepAwaited<T> = T extends Promise<infer A> ? DeepAwaited<A> : T extends Record<infer A, Promise<infer B>> ? {
38
- [K in A]: DeepAwaited<B>;
39
- } : T;
40
- declare type PathParamMask<TRoutePath extends string> = TRoutePath extends `${infer L}/:${infer C}/${infer R}` ? PathParamMask<`${L}/${string}/${R}`> : TRoutePath extends `${infer L}/:${infer C}` ? PathParamMask<`${L}/${string}`> : TRoutePath;
41
- declare type Timeout = ReturnType<typeof setTimeout>;
42
- declare type Updater<TPrevious, TResult = TPrevious> = TResult | ((prev?: TPrevious) => TResult);
43
- declare type PickExtract<T, U> = {
44
- [K in keyof T as T[K] extends U ? K : never]: T[K];
45
- };
46
- declare type PickExclude<T, U> = {
47
- [K in keyof T as T[K] extends U ? never : K]: T[K];
48
- };
49
- /**
50
- * This function returns `a` if `b` is deeply equal.
51
- * If not, it will replace any deeply equal children of `b` with those of `a`.
52
- * This can be used for structural sharing between JSON values for example.
53
- */
54
- declare function replaceEqualDeep(prev: any, next: any): any;
55
- declare function last<T>(arr: T[]): T | undefined;
56
- declare function warning(cond: any, message: string): cond is true;
57
- declare function functionalUpdate<TResult>(updater: Updater<TResult>, previous: TResult): TResult;
58
- declare function pick<T, K extends keyof T>(parent: T, keys: K[]): Pick<T, K>;
59
-
60
19
  interface RouteMatch<TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo, TRouteInfo extends AnyRouteInfo = RouteInfo> extends Route<TAllRouteInfo, TRouteInfo> {
61
20
  matchId: string;
62
21
  pathname: string;
@@ -73,20 +32,14 @@ interface RouteMatch<TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo
73
32
  loaderData: TRouteInfo['loaderData'];
74
33
  routeLoaderData: TRouteInfo['routeLoaderData'];
75
34
  isFetching: boolean;
76
- isPending: boolean;
77
35
  invalidAt: number;
78
36
  __: {
79
- element?: GetFrameworkGeneric<'Element'>;
80
- errorElement?: GetFrameworkGeneric<'Element'>;
81
- catchElement?: GetFrameworkGeneric<'Element'>;
82
- pendingElement?: GetFrameworkGeneric<'Element'>;
37
+ component?: GetFrameworkGeneric<'Component'>;
38
+ errorComponent?: GetFrameworkGeneric<'Component'>;
39
+ pendingComponent?: GetFrameworkGeneric<'Component'>;
83
40
  loadPromise?: Promise<void>;
84
- loaderDataPromise?: Promise<void>;
85
- elementsPromise?: Promise<void>;
41
+ componentsPromise?: Promise<void>;
86
42
  dataPromise?: Promise<void>;
87
- pendingTimeout?: Timeout;
88
- pendingMinTimeout?: Timeout;
89
- pendingMinPromise?: Promise<void>;
90
43
  onExit?: void | ((matchContext: {
91
44
  params: TRouteInfo['allParams'];
92
45
  search: TRouteInfo['fullSearchSchema'];
@@ -94,15 +47,11 @@ interface RouteMatch<TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo
94
47
  abortController: AbortController;
95
48
  latestId: string;
96
49
  validate: () => void;
97
- startPending: () => void;
98
- cancelPending: () => void;
99
50
  notify: () => void;
100
51
  resolve: () => void;
101
52
  };
102
53
  cancel: () => void;
103
54
  load: (loaderOpts?: {
104
- withPending?: boolean;
105
- } & ({
106
55
  preload: true;
107
56
  maxAge: number;
108
57
  gcMaxAge: number;
@@ -110,7 +59,7 @@ interface RouteMatch<TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo
110
59
  preload?: false;
111
60
  maxAge?: never;
112
61
  gcMaxAge?: never;
113
- })) => Promise<TRouteInfo['routeLoaderData']>;
62
+ }) => Promise<TRouteInfo['routeLoaderData']>;
114
63
  fetch: (opts?: {
115
64
  maxAge?: number;
116
65
  }) => Promise<TRouteInfo['routeLoaderData']>;
@@ -123,6 +72,47 @@ declare function createRouteMatch<TAllRouteInfo extends AnyAllRouteInfo = Defaul
123
72
  pathname: string;
124
73
  }): RouteMatch<TAllRouteInfo, TRouteInfo>;
125
74
 
75
+ declare type NoInfer<T> = [T][T extends any ? 0 : never];
76
+ declare type IsAny<T, Y, N> = 1 extends 0 & T ? Y : N;
77
+ declare type IsAnyBoolean<T> = 1 extends 0 & T ? true : false;
78
+ declare type IsKnown<T, Y, N> = unknown extends T ? N : Y;
79
+ declare type PickAsRequired<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;
80
+ declare type PickAsPartial<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
81
+ declare type PickUnsafe<T, K> = K extends keyof T ? Pick<T, K> : never;
82
+ declare type PickExtra<T, K> = Expand<{
83
+ [TKey in keyof K as string extends TKey ? never : TKey extends keyof T ? never : TKey]: K[TKey];
84
+ }>;
85
+ declare type PickRequired<T> = {
86
+ [K in keyof T as undefined extends T[K] ? never : K]: T[K];
87
+ };
88
+ declare type Expand<T> = T extends object ? T extends infer O ? {
89
+ [K in keyof O]: O[K];
90
+ } : never : T;
91
+ declare type Values<O> = O[ValueKeys<O>];
92
+ declare type ValueKeys<O> = Extract<keyof O, PropertyKey>;
93
+ declare type DeepAwaited<T> = T extends Promise<infer A> ? DeepAwaited<A> : T extends Record<infer A, Promise<infer B>> ? {
94
+ [K in A]: DeepAwaited<B>;
95
+ } : T;
96
+ declare type PathParamMask<TRoutePath extends string> = TRoutePath extends `${infer L}/:${infer C}/${infer R}` ? PathParamMask<`${L}/${string}/${R}`> : TRoutePath extends `${infer L}/:${infer C}` ? PathParamMask<`${L}/${string}`> : TRoutePath;
97
+ declare type Timeout = ReturnType<typeof setTimeout>;
98
+ declare type Updater<TPrevious, TResult = TPrevious> = TResult | ((prev?: TPrevious) => TResult);
99
+ declare type PickExtract<T, U> = {
100
+ [K in keyof T as T[K] extends U ? K : never]: T[K];
101
+ };
102
+ declare type PickExclude<T, U> = {
103
+ [K in keyof T as T[K] extends U ? never : K]: T[K];
104
+ };
105
+ /**
106
+ * This function returns `a` if `b` is deeply equal.
107
+ * If not, it will replace any deeply equal children of `b` with those of `a`.
108
+ * This can be used for structural sharing between JSON values for example.
109
+ */
110
+ declare function replaceEqualDeep(prev: any, next: any): any;
111
+ declare function last<T>(arr: T[]): T | undefined;
112
+ declare function warning(cond: any, message: string): cond is true;
113
+ declare function functionalUpdate<TResult>(updater: Updater<TResult>, previous: TResult): TResult;
114
+ declare function pick<T, K extends keyof T>(parent: T, keys: K[]): Pick<T, K>;
115
+
126
116
  interface LocationState {
127
117
  }
128
118
  interface Location<TSearchObj extends AnySearchSchema = {}, TState extends LocationState = LocationState> {
@@ -153,12 +143,9 @@ interface RouterOptions<TRouteConfig extends AnyRouteConfig> {
153
143
  defaultPreloadGcMaxAge?: number;
154
144
  defaultPreloadDelay?: number;
155
145
  useErrorBoundary?: boolean;
156
- defaultElement?: GetFrameworkGeneric<'Element'>;
157
- defaultErrorElement?: GetFrameworkGeneric<'Element'>;
158
- defaultCatchElement?: GetFrameworkGeneric<'Element'>;
159
- defaultPendingElement?: GetFrameworkGeneric<'Element'>;
160
- defaultPendingMs?: number;
161
- defaultPendingMinMs?: number;
146
+ defaultComponent?: GetFrameworkGeneric<'Component'>;
147
+ defaultErrorComponent?: GetFrameworkGeneric<'Component'>;
148
+ defaultPendingComponent?: GetFrameworkGeneric<'Component'>;
162
149
  defaultLoaderMaxAge?: number;
163
150
  defaultLoaderGcMaxAge?: number;
164
151
  caseSensitive?: boolean;
@@ -169,7 +156,7 @@ interface RouterOptions<TRouteConfig extends AnyRouteConfig> {
169
156
  route: AnyRoute;
170
157
  router: Router<any, any>;
171
158
  }) => void;
172
- createElement?: (element: GetFrameworkGeneric<'SyncOrAsyncElement'>) => Promise<GetFrameworkGeneric<'Element'>>;
159
+ loadComponent?: (component: GetFrameworkGeneric<'Component'>) => Promise<GetFrameworkGeneric<'Component'>>;
173
160
  }
174
161
  interface Action<TPayload = unknown, TResponse = unknown> {
175
162
  submit: (submission?: TPayload, actionOpts?: {
@@ -295,8 +282,6 @@ interface Router<TRouteConfig extends AnyRouteConfig = RouteConfig, TAllRouteInf
295
282
  strictParseParams?: boolean;
296
283
  }) => RouteMatch[];
297
284
  loadMatches: (resolvedMatches: RouteMatch[], loaderOpts?: {
298
- withPending?: boolean;
299
- } & ({
300
285
  preload: true;
301
286
  maxAge: number;
302
287
  gcMaxAge: number;
@@ -304,7 +289,7 @@ interface Router<TRouteConfig extends AnyRouteConfig = RouteConfig, TAllRouteInf
304
289
  preload?: false;
305
290
  maxAge?: never;
306
291
  gcMaxAge?: never;
307
- })) => Promise<void>;
292
+ }) => Promise<void>;
308
293
  invalidateRoute: (opts: MatchLocation) => void;
309
294
  reload: () => Promise<void>;
310
295
  resolvePath: (from: string, path: string) => string;
@@ -442,12 +427,9 @@ declare type RouteOptions<TRouteId extends string = string, TPath extends string
442
427
  validateSearch?: SearchSchemaValidator<TSearchSchema, TParentSearchSchema>;
443
428
  preSearchFilters?: SearchFilter<TFullSearchSchema>[];
444
429
  postSearchFilters?: SearchFilter<TFullSearchSchema>[];
445
- pendingMs?: number;
446
- pendingMinMs?: number;
447
- element?: GetFrameworkGeneric<'SyncOrAsyncElement'>;
448
- errorElement?: GetFrameworkGeneric<'SyncOrAsyncElement'>;
449
- catchElement?: GetFrameworkGeneric<'SyncOrAsyncElement'>;
450
- pendingElement?: GetFrameworkGeneric<'SyncOrAsyncElement'>;
430
+ component?: GetFrameworkGeneric<'Component'>;
431
+ errorComponent?: GetFrameworkGeneric<'Component'>;
432
+ pendingComponent?: GetFrameworkGeneric<'Component'>;
451
433
  loader?: LoaderFn<TRouteLoaderData, TFullSearchSchema, TAllParams>;
452
434
  loaderMaxAge?: number;
453
435
  loaderGcMaxAge?: number;
@@ -1382,7 +1382,7 @@
1382
1382
  };
1383
1383
  };
1384
1384
 
1385
- const elementTypes = ['element', 'errorElement', 'catchElement', 'pendingElement'];
1385
+ const componentTypes = ['component', 'errorComponent', 'pendingComponent'];
1386
1386
  function createRouteMatch(router, route, opts) {
1387
1387
  const routeMatch = _extends({}, route, opts, {
1388
1388
  router,
@@ -1392,7 +1392,6 @@
1392
1392
  status: 'idle',
1393
1393
  routeLoaderData: {},
1394
1394
  loaderData: {},
1395
- isPending: false,
1396
1395
  isFetching: false,
1397
1396
  isInvalid: false,
1398
1397
  invalidAt: Infinity,
@@ -1410,32 +1409,6 @@
1410
1409
 
1411
1410
  routeMatch.router.notify();
1412
1411
  },
1413
- startPending: () => {
1414
- var _routeMatch$options$p, _routeMatch$options$p2;
1415
-
1416
- const pendingMs = (_routeMatch$options$p = routeMatch.options.pendingMs) != null ? _routeMatch$options$p : router.options.defaultPendingMs;
1417
- const pendingMinMs = (_routeMatch$options$p2 = routeMatch.options.pendingMinMs) != null ? _routeMatch$options$p2 : router.options.defaultPendingMinMs;
1418
-
1419
- if (routeMatch.__.pendingTimeout || routeMatch.status !== 'loading' || typeof pendingMs === 'undefined') {
1420
- return;
1421
- }
1422
-
1423
- routeMatch.__.pendingTimeout = setTimeout(() => {
1424
- routeMatch.isPending = true;
1425
-
1426
- routeMatch.__.resolve();
1427
-
1428
- if (typeof pendingMinMs !== 'undefined') {
1429
- routeMatch.__.pendingMinPromise = new Promise(r => routeMatch.__.pendingMinTimeout = setTimeout(r, pendingMinMs));
1430
- }
1431
- }, pendingMs);
1432
- },
1433
- cancelPending: () => {
1434
- routeMatch.isPending = false;
1435
- clearTimeout(routeMatch.__.pendingTimeout);
1436
- clearTimeout(routeMatch.__.pendingMinTimeout);
1437
- delete routeMatch.__.pendingMinPromise;
1438
- },
1439
1412
  validate: () => {
1440
1413
  var _routeMatch$parentMat, _routeMatch$parentMat2;
1441
1414
 
@@ -1455,11 +1428,11 @@
1455
1428
 
1456
1429
  routeMatch.routeSearch = nextSearch;
1457
1430
  routeMatch.search = replaceEqualDeep(parentSearch, _extends({}, parentSearch, nextSearch));
1458
- elementTypes.map(async type => {
1459
- const routeElement = routeMatch.options[type];
1431
+ componentTypes.map(async type => {
1432
+ const component = routeMatch.options[type];
1460
1433
 
1461
1434
  if (typeof routeMatch.__[type] !== 'function') {
1462
- routeMatch.__[type] = routeElement;
1435
+ routeMatch.__[type] = component;
1463
1436
  }
1464
1437
  });
1465
1438
  } catch (err) {
@@ -1479,14 +1452,16 @@
1479
1452
  var _routeMatch$__$abortC;
1480
1453
 
1481
1454
  (_routeMatch$__$abortC = routeMatch.__.abortController) == null ? void 0 : _routeMatch$__$abortC.abort();
1482
-
1483
- routeMatch.__.cancelPending();
1484
1455
  },
1485
1456
  invalidate: () => {
1486
1457
  routeMatch.isInvalid = true;
1487
1458
  },
1488
1459
  hasLoaders: () => {
1489
- return !!(route.options.loader || elementTypes.some(d => typeof route.options[d] === 'function'));
1460
+ return !!(route.options.loader || componentTypes.some(d => {
1461
+ var _route$options$d;
1462
+
1463
+ return (_route$options$d = route.options[d]) == null ? void 0 : _route$options$d.preload;
1464
+ }));
1490
1465
  },
1491
1466
  load: async loaderOpts => {
1492
1467
  const now = Date.now();
@@ -1530,91 +1505,79 @@
1530
1505
  routeMatch.isFetching = true;
1531
1506
  routeMatch.__.resolve = resolve;
1532
1507
 
1533
- routeMatch.__.loaderDataPromise = (async () => {
1534
- // Load the elements and data in parallel
1535
- routeMatch.__.elementsPromise = (async () => {
1536
- // then run all element and data loaders in parallel
1537
- // For each element type, potentially load it asynchronously
1538
- await Promise.all(elementTypes.map(async type => {
1539
- const routeElement = routeMatch.options[type];
1508
+ routeMatch.__.componentsPromise = (async () => {
1509
+ // then run all component and data loaders in parallel
1510
+ // For each component type, potentially load it asynchronously
1511
+ await Promise.all(componentTypes.map(async type => {
1512
+ var _routeMatch$__$type;
1540
1513
 
1541
- if (typeof routeMatch.__[type] === 'function') {
1542
- routeMatch.__[type] = await router.options.createElement(routeElement);
1543
- }
1544
- }));
1545
- })();
1546
-
1547
- routeMatch.__.dataPromise = Promise.resolve().then(async () => {
1548
- try {
1549
- var _ref, _ref2, _opts$maxAge;
1550
-
1551
- if (routeMatch.options.loader) {
1552
- const data = await routeMatch.options.loader({
1553
- params: routeMatch.params,
1554
- search: routeMatch.routeSearch,
1555
- signal: routeMatch.__.abortController.signal
1556
- });
1557
-
1558
- if (id !== routeMatch.__.latestId) {
1559
- return routeMatch.__.loadPromise;
1560
- }
1514
+ const component = routeMatch.options[type];
1561
1515
 
1562
- routeMatch.routeLoaderData = replaceEqualDeep(routeMatch.routeLoaderData, data);
1563
- }
1516
+ if ((_routeMatch$__$type = routeMatch.__[type]) != null && _routeMatch$__$type.preload) {
1517
+ routeMatch.__[type] = await router.options.loadComponent(component);
1518
+ }
1519
+ }));
1520
+ })();
1521
+
1522
+ routeMatch.__.dataPromise = Promise.resolve().then(async () => {
1523
+ try {
1524
+ var _ref, _ref2, _opts$maxAge;
1525
+
1526
+ if (routeMatch.options.loader) {
1527
+ const data = await routeMatch.options.loader({
1528
+ params: routeMatch.params,
1529
+ search: routeMatch.routeSearch,
1530
+ signal: routeMatch.__.abortController.signal
1531
+ });
1564
1532
 
1565
- routeMatch.error = undefined;
1566
- routeMatch.status = 'success';
1567
- routeMatch.updatedAt = Date.now();
1568
- routeMatch.invalidAt = routeMatch.updatedAt + ((_ref = (_ref2 = (_opts$maxAge = opts == null ? void 0 : opts.maxAge) != null ? _opts$maxAge : routeMatch.options.loaderMaxAge) != null ? _ref2 : router.options.defaultLoaderMaxAge) != null ? _ref : 0);
1569
- } catch (err) {
1570
1533
  if (id !== routeMatch.__.latestId) {
1571
1534
  return routeMatch.__.loadPromise;
1572
1535
  }
1573
1536
 
1574
- {
1575
- console.error(err);
1576
- }
1577
-
1578
- routeMatch.error = err;
1579
- routeMatch.status = 'error';
1580
- routeMatch.updatedAt = Date.now();
1537
+ routeMatch.routeLoaderData = replaceEqualDeep(routeMatch.routeLoaderData, data);
1581
1538
  }
1582
- });
1583
-
1584
- try {
1585
- await Promise.all([routeMatch.__.elementsPromise, routeMatch.__.dataPromise]);
1586
1539
 
1540
+ routeMatch.error = undefined;
1541
+ routeMatch.status = 'success';
1542
+ routeMatch.updatedAt = Date.now();
1543
+ routeMatch.invalidAt = routeMatch.updatedAt + ((_ref = (_ref2 = (_opts$maxAge = opts == null ? void 0 : opts.maxAge) != null ? _opts$maxAge : routeMatch.options.loaderMaxAge) != null ? _ref2 : router.options.defaultLoaderMaxAge) != null ? _ref : 0);
1544
+ } catch (err) {
1587
1545
  if (id !== routeMatch.__.latestId) {
1588
1546
  return routeMatch.__.loadPromise;
1589
1547
  }
1590
1548
 
1591
- if (routeMatch.__.pendingMinPromise) {
1592
- await routeMatch.__.pendingMinPromise;
1593
- delete routeMatch.__.pendingMinPromise;
1594
- }
1595
- } finally {
1596
- if (id !== routeMatch.__.latestId) {
1597
- return routeMatch.__.loadPromise;
1549
+ {
1550
+ console.error(err);
1598
1551
  }
1599
1552
 
1600
- routeMatch.__.cancelPending();
1553
+ routeMatch.error = err;
1554
+ routeMatch.status = 'error';
1555
+ routeMatch.updatedAt = Date.now();
1556
+ }
1557
+ });
1601
1558
 
1602
- routeMatch.isPending = false;
1603
- routeMatch.isFetching = false;
1559
+ try {
1560
+ await Promise.all([routeMatch.__.componentsPromise, routeMatch.__.dataPromise]);
1604
1561
 
1605
- routeMatch.__.notify();
1562
+ if (id !== routeMatch.__.latestId) {
1563
+ return routeMatch.__.loadPromise;
1564
+ }
1565
+ } finally {
1566
+ if (id !== routeMatch.__.latestId) {
1567
+ return routeMatch.__.loadPromise;
1606
1568
  }
1607
- })();
1608
1569
 
1609
- await routeMatch.__.loaderDataPromise;
1570
+ routeMatch.isFetching = false;
1610
1571
 
1611
- if (id !== routeMatch.__.latestId) {
1612
- return routeMatch.__.loadPromise;
1572
+ routeMatch.__.notify();
1613
1573
  }
1614
-
1615
- delete routeMatch.__.loaderDataPromise;
1616
1574
  });
1617
1575
  await routeMatch.__.loadPromise;
1576
+
1577
+ if (id !== routeMatch.__.latestId) {
1578
+ return routeMatch.__.loadPromise;
1579
+ }
1580
+
1618
1581
  delete routeMatch.__.loadPromise;
1619
1582
  }
1620
1583
  });
@@ -1738,10 +1701,16 @@
1738
1701
  return router.routesById[id];
1739
1702
  },
1740
1703
  notify: () => {
1741
- router.state = _extends({}, router.state, {
1742
- isFetching: router.state.status === 'loading' || router.state.matches.some(d => d.isFetching),
1743
- isPreloading: Object.values(router.matchCache).some(d => d.match.isFetching && !router.state.matches.find(dd => dd.matchId === d.match.matchId))
1744
- });
1704
+ const isFetching = router.state.status === 'loading' || router.state.matches.some(d => d.isFetching);
1705
+ const isPreloading = Object.values(router.matchCache).some(d => d.match.isFetching && !router.state.matches.find(dd => dd.matchId === d.match.matchId));
1706
+
1707
+ if (router.state.isFetching !== isFetching || router.state.isPreloading !== isPreloading) {
1708
+ router.state = _extends({}, router.state, {
1709
+ isFetching,
1710
+ isPreloading
1711
+ });
1712
+ }
1713
+
1745
1714
  cascadeLoaderData(router.state.matches);
1746
1715
  router.listeners.forEach(listener => listener(router));
1747
1716
  },
@@ -1760,7 +1729,7 @@
1760
1729
  invariant(dehydratedMatch, 'Oh no! Dehydrated route matches did not match the active state of the router 😬');
1761
1730
  Object.assign(match, dehydratedMatch);
1762
1731
  });
1763
- router.loadMatches(matches);
1732
+ matches.forEach(match => match.__.validate());
1764
1733
  router.state = _extends({}, router.state, dehydratedState, {
1765
1734
  matches
1766
1735
  });
@@ -1776,8 +1745,11 @@
1776
1745
 
1777
1746
  if (next.href !== router.location.href) {
1778
1747
  router.__.commitLocation(next, true);
1779
- } // router.load()
1748
+ }
1780
1749
 
1750
+ if (!router.state.matches.length) {
1751
+ router.load();
1752
+ }
1781
1753
 
1782
1754
  const unsub = router.history.listen(event => {
1783
1755
  router.load(router.__.parseLocation(event.location, router.location));
@@ -1850,18 +1822,26 @@
1850
1822
  const matches = router.matchRoutes(router.location.pathname, {
1851
1823
  strictParseParams: true
1852
1824
  });
1853
- router.state = _extends({}, router.state, {
1854
- pending: {
1825
+
1826
+ if (typeof document !== 'undefined') {
1827
+ router.state = _extends({}, router.state, {
1828
+ pending: {
1829
+ matches: matches,
1830
+ location: router.location
1831
+ },
1832
+ status: 'loading'
1833
+ });
1834
+ } else {
1835
+ router.state = _extends({}, router.state, {
1855
1836
  matches: matches,
1856
- location: router.location
1857
- },
1858
- status: 'loading'
1859
- });
1837
+ location: router.location,
1838
+ status: 'loading'
1839
+ });
1840
+ }
1841
+
1860
1842
  router.notify(); // Load the matches
1861
1843
 
1862
- await router.loadMatches(matches, {
1863
- withPending: true
1864
- });
1844
+ await router.loadMatches(matches);
1865
1845
 
1866
1846
  if (router.startedLoadingAt !== id) {
1867
1847
  // Ignore side-effects of match loading
@@ -2083,14 +2063,8 @@
2083
2063
 
2084
2064
  match.load(loaderOpts);
2085
2065
 
2086
- if (match.status === 'loading') {
2087
- // If requested, start the pending timers
2088
- if (loaderOpts != null && loaderOpts.withPending) match.__.startPending();
2089
- }
2090
-
2091
2066
  if (match.__.loadPromise) {
2092
2067
  // Wait for the first sign of activity from the match
2093
- // This might be completion, error, or a pending state
2094
2068
  await match.__.loadPromise;
2095
2069
  }
2096
2070
  });