@tanstack/react-router 0.0.1-beta.279 → 0.0.1-beta.280
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/Matches.js.map +1 -1
- package/build/cjs/RouterProvider.js +1 -2
- package/build/cjs/RouterProvider.js.map +1 -1
- package/build/cjs/link.js +1 -1
- package/build/cjs/link.js.map +1 -1
- package/build/cjs/route.js.map +1 -1
- package/build/cjs/router.js +54 -91
- package/build/cjs/router.js.map +1 -1
- package/build/esm/index.js +56 -94
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +1 -1
- package/build/stats-react.json +355 -355
- package/build/types/Matches.d.ts +0 -1
- package/build/types/fileRoute.d.ts +4 -0
- package/build/types/route.d.ts +4 -1
- package/build/types/router.d.ts +5 -3
- package/build/umd/index.development.js +56 -94
- 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/Matches.tsx +0 -1
- package/src/RouterProvider.tsx +1 -2
- package/src/link.tsx +1 -1
- package/src/route.ts +4 -10
- package/src/router.ts +86 -123
package/build/esm/index.js
CHANGED
|
@@ -584,7 +584,6 @@ function Transitioner() {
|
|
|
584
584
|
}
|
|
585
585
|
}
|
|
586
586
|
}
|
|
587
|
-
router.pendingMatches = [];
|
|
588
587
|
router.__store.setState(s => ({
|
|
589
588
|
...s,
|
|
590
589
|
isTransitioning: false,
|
|
@@ -600,7 +599,7 @@ function Transitioner() {
|
|
|
600
599
|
return null;
|
|
601
600
|
}
|
|
602
601
|
function getRouteMatch(state, id) {
|
|
603
|
-
return [...state.
|
|
602
|
+
return [...state.cachedMatches, ...(state.pendingMatches ?? []), ...state.matches].find(d => d.id === id);
|
|
604
603
|
}
|
|
605
604
|
function useRouterState(opts) {
|
|
606
605
|
const router = useRouter();
|
|
@@ -1147,7 +1146,7 @@ function useLinkProps(options) {
|
|
|
1147
1146
|
// Combine the matches based on user router.options
|
|
1148
1147
|
const pathTest = activeOptions?.exact ? s.location.pathname === next.pathname : pathIsFuzzyEqual;
|
|
1149
1148
|
const hashTest = activeOptions?.includeHash ? s.location.hash === next.hash : true;
|
|
1150
|
-
const searchTest = activeOptions?.includeSearch ?? true ? deepEqual(s.location.search, next.search,
|
|
1149
|
+
const searchTest = activeOptions?.includeSearch ?? true ? deepEqual(s.location.search, next.search, !activeOptions?.exact) : true;
|
|
1151
1150
|
|
|
1152
1151
|
// The final "active" test
|
|
1153
1152
|
return pathTest && hashTest && searchTest;
|
|
@@ -1394,7 +1393,6 @@ class Router {
|
|
|
1394
1393
|
navigateTimeout = null;
|
|
1395
1394
|
latestLoadPromise = Promise.resolve();
|
|
1396
1395
|
subscribers = new Set();
|
|
1397
|
-
pendingMatches = [];
|
|
1398
1396
|
injectedHtml = [];
|
|
1399
1397
|
|
|
1400
1398
|
// Must build in constructor
|
|
@@ -1718,7 +1716,6 @@ class Router {
|
|
|
1718
1716
|
routeContext: undefined,
|
|
1719
1717
|
context: undefined,
|
|
1720
1718
|
abortController: new AbortController(),
|
|
1721
|
-
shouldReloadDeps: undefined,
|
|
1722
1719
|
fetchCount: 0,
|
|
1723
1720
|
cause,
|
|
1724
1721
|
loaderDeps
|
|
@@ -1930,9 +1927,10 @@ class Router {
|
|
|
1930
1927
|
let latestPromise;
|
|
1931
1928
|
let firstBadMatchIndex;
|
|
1932
1929
|
const updateMatch = match => {
|
|
1933
|
-
// const isPreload = this.state.
|
|
1930
|
+
// const isPreload = this.state.cachedMatches.find((d) => d.id === match.id)
|
|
1934
1931
|
const isPending = this.state.pendingMatches?.find(d => d.id === match.id);
|
|
1935
|
-
const
|
|
1932
|
+
const isMatched = this.state.matches.find(d => d.id === match.id);
|
|
1933
|
+
const matchesKey = isPending ? 'pendingMatches' : isMatched ? 'matches' : 'cachedMatches';
|
|
1936
1934
|
this.__store.setState(s => ({
|
|
1937
1935
|
...s,
|
|
1938
1936
|
[matchesKey]: s[matchesKey]?.map(d => d.id === match.id ? match : d)
|
|
@@ -2057,65 +2055,24 @@ class Router {
|
|
|
2057
2055
|
}),
|
|
2058
2056
|
cause: preload ? 'preload' : match.cause
|
|
2059
2057
|
};
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
let shouldLoad = true;
|
|
2063
|
-
const shouldReloadFn = route.options.shouldReload;
|
|
2064
|
-
let shouldReloadDeps = typeof shouldReloadFn === 'function' ? shouldReloadFn(loaderContext) : !!(shouldReloadFn ?? true);
|
|
2065
|
-
const compareDeps = () => {
|
|
2066
|
-
if (typeof shouldReloadDeps === 'object') {
|
|
2067
|
-
// compare the deps to see if they've changed
|
|
2068
|
-
shouldLoad = !deepEqual(shouldReloadDeps, match.shouldReloadDeps);
|
|
2069
|
-
} else {
|
|
2070
|
-
shouldLoad = !!shouldReloadDeps;
|
|
2071
|
-
}
|
|
2072
|
-
};
|
|
2073
|
-
|
|
2074
|
-
// If it's the first preload, or the route is entering, or we're
|
|
2075
|
-
// invalidating, we definitely need to load the route
|
|
2076
|
-
if (invalidate) ; else if (preload) {
|
|
2077
|
-
if (!match.fetchCount) ; else {
|
|
2078
|
-
compareDeps();
|
|
2079
|
-
}
|
|
2080
|
-
} else if (match.cause === 'enter') {
|
|
2081
|
-
if (!match.fetchCount) ; else {
|
|
2082
|
-
compareDeps();
|
|
2083
|
-
}
|
|
2084
|
-
} else {
|
|
2085
|
-
compareDeps();
|
|
2086
|
-
}
|
|
2087
|
-
if (typeof shouldReloadDeps === 'object') {
|
|
2088
|
-
matches[index] = match = {
|
|
2089
|
-
...match,
|
|
2090
|
-
shouldReloadDeps
|
|
2091
|
-
};
|
|
2058
|
+
if (match.fetchCount && match.status === 'success') {
|
|
2059
|
+
resolve();
|
|
2092
2060
|
}
|
|
2093
2061
|
|
|
2094
|
-
//
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
}
|
|
2100
|
-
|
|
2101
|
-
|
|
2062
|
+
// Otherwise, load the route
|
|
2063
|
+
matches[index] = match = {
|
|
2064
|
+
...match,
|
|
2065
|
+
isFetching: true,
|
|
2066
|
+
fetchCount: match.fetchCount + 1
|
|
2067
|
+
};
|
|
2068
|
+
const componentsPromise = Promise.all(componentTypes.map(async type => {
|
|
2069
|
+
const component = route.options[type];
|
|
2070
|
+
if (component?.preload) {
|
|
2071
|
+
await component.preload();
|
|
2102
2072
|
}
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
...match,
|
|
2107
|
-
isFetching: true,
|
|
2108
|
-
fetchCount: match.fetchCount + 1
|
|
2109
|
-
};
|
|
2110
|
-
const componentsPromise = Promise.all(componentTypes.map(async type => {
|
|
2111
|
-
const component = route.options[type];
|
|
2112
|
-
if (component?.preload) {
|
|
2113
|
-
await component.preload();
|
|
2114
|
-
}
|
|
2115
|
-
}));
|
|
2116
|
-
const loaderPromise = route.options.loader?.(loaderContext);
|
|
2117
|
-
loadPromise = Promise.all([componentsPromise, loaderPromise]).then(d => d[1]);
|
|
2118
|
-
}
|
|
2073
|
+
}));
|
|
2074
|
+
const loaderPromise = route.options.loader?.(loaderContext);
|
|
2075
|
+
loadPromise = Promise.all([componentsPromise, loaderPromise]).then(d => d[1]);
|
|
2119
2076
|
}
|
|
2120
2077
|
matches[index] = match = {
|
|
2121
2078
|
...match,
|
|
@@ -2154,24 +2111,23 @@ class Router {
|
|
|
2154
2111
|
...match,
|
|
2155
2112
|
error,
|
|
2156
2113
|
status: 'error',
|
|
2157
|
-
isFetching: false
|
|
2158
|
-
updatedAt: Date.now()
|
|
2114
|
+
isFetching: false
|
|
2159
2115
|
};
|
|
2160
|
-
} finally {
|
|
2161
|
-
// If we showed the pending component, that means
|
|
2162
|
-
// we already moved the pendingMatches to the matches
|
|
2163
|
-
// state, so we need to update that specific match
|
|
2164
|
-
if (didShowPending && pendingMinMs && match.showPending) {
|
|
2165
|
-
updateMatch(match);
|
|
2166
|
-
}
|
|
2167
2116
|
}
|
|
2168
2117
|
updateMatch(match);
|
|
2169
2118
|
};
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2119
|
+
|
|
2120
|
+
// This is where all of the stale-while-revalidate magic happens
|
|
2121
|
+
const age = Date.now() - match.updatedAt;
|
|
2122
|
+
let staleAge = preload ? route.options.preloadStaleTime ?? this.options.defaultPreloadStaleTime ?? 30_000 // 30 seconds for preloads by default
|
|
2123
|
+
: route.options.staleTime ?? this.options.defaultStaleTime ?? 0;
|
|
2124
|
+
if (match.status === 'success') {
|
|
2125
|
+
// Background Fetching, no need to wait
|
|
2126
|
+
if (age > staleAge) {
|
|
2127
|
+
fetch();
|
|
2128
|
+
}
|
|
2173
2129
|
} else {
|
|
2174
|
-
// Critical Fetching
|
|
2130
|
+
// Critical Fetching, we need to await
|
|
2175
2131
|
|
|
2176
2132
|
// If we need to potentially show the pending component,
|
|
2177
2133
|
// start a timer to show it after the pendingMs
|
|
@@ -2190,9 +2146,6 @@ class Router {
|
|
|
2190
2146
|
await fetch();
|
|
2191
2147
|
}
|
|
2192
2148
|
resolve();
|
|
2193
|
-
// No Fetching
|
|
2194
|
-
|
|
2195
|
-
resolve();
|
|
2196
2149
|
}));
|
|
2197
2150
|
});
|
|
2198
2151
|
await Promise.all(matchPromises);
|
|
@@ -2219,12 +2172,16 @@ class Router {
|
|
|
2219
2172
|
let pendingMatches;
|
|
2220
2173
|
const previousMatches = this.state.matches;
|
|
2221
2174
|
this.__store.batch(() => {
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2175
|
+
// This is where all of the garbage collection magic happens
|
|
2176
|
+
this.__store.setState(s => {
|
|
2177
|
+
return {
|
|
2178
|
+
...s,
|
|
2179
|
+
cachedMatches: s.cachedMatches.filter(d => {
|
|
2180
|
+
const route = this.looseRoutesById[d.routeId];
|
|
2181
|
+
return d.status !== 'error' && Date.now() - d.updatedAt < (route.options.gcTime ?? this.options.defaultGcTime ?? 5 * 60 * 1000);
|
|
2182
|
+
})
|
|
2183
|
+
};
|
|
2184
|
+
});
|
|
2228
2185
|
|
|
2229
2186
|
// Match the routes
|
|
2230
2187
|
pendingMatches = this.matchRoutes(next.pathname, next.search, {
|
|
@@ -2232,12 +2189,13 @@ class Router {
|
|
|
2232
2189
|
});
|
|
2233
2190
|
|
|
2234
2191
|
// Ingest the new matches
|
|
2192
|
+
// If a cached moved to pendingMatches, remove it from cachedMatches
|
|
2235
2193
|
this.__store.setState(s => ({
|
|
2236
2194
|
...s,
|
|
2237
2195
|
isLoading: true,
|
|
2238
2196
|
location: next,
|
|
2239
2197
|
pendingMatches,
|
|
2240
|
-
|
|
2198
|
+
cachedMatches: s.cachedMatches.filter(d => {
|
|
2241
2199
|
return !pendingMatches.find(e => e.id === d.id);
|
|
2242
2200
|
})
|
|
2243
2201
|
}));
|
|
@@ -2259,19 +2217,23 @@ class Router {
|
|
|
2259
2217
|
if (latestPromise = this.checkLatest(promise)) {
|
|
2260
2218
|
return latestPromise;
|
|
2261
2219
|
}
|
|
2262
|
-
const
|
|
2263
|
-
const
|
|
2264
|
-
const
|
|
2220
|
+
const exitingMatches = previousMatches.filter(match => !pendingMatches.find(d => d.id === match.id));
|
|
2221
|
+
const enteringMatches = pendingMatches.filter(match => !previousMatches.find(d => d.id === match.id));
|
|
2222
|
+
const stayingMatches = previousMatches.filter(match => pendingMatches.find(d => d.id === match.id));
|
|
2223
|
+
|
|
2224
|
+
// Commit the pending matches. If a previous match was
|
|
2225
|
+
// removed, place it in the cachedMatches
|
|
2265
2226
|
this.__store.setState(s => ({
|
|
2266
2227
|
...s,
|
|
2267
2228
|
isLoading: false,
|
|
2268
2229
|
matches: pendingMatches,
|
|
2269
|
-
pendingMatches: undefined
|
|
2230
|
+
pendingMatches: undefined,
|
|
2231
|
+
cachedMatches: [...s.cachedMatches, ...exitingMatches.filter(d => d.status !== 'error')]
|
|
2270
2232
|
}))
|
|
2271
2233
|
|
|
2272
2234
|
//
|
|
2273
2235
|
;
|
|
2274
|
-
[[
|
|
2236
|
+
[[exitingMatches, 'onLeave'], [enteringMatches, 'onEnter'], [stayingMatches, 'onStay']].forEach(([matches, hook]) => {
|
|
2275
2237
|
matches.forEach(match => {
|
|
2276
2238
|
this.looseRoutesById[match.routeId].options[hook]?.(match);
|
|
2277
2239
|
});
|
|
@@ -2299,13 +2261,13 @@ class Router {
|
|
|
2299
2261
|
let matches = this.matchRoutes(next.pathname, next.search, {
|
|
2300
2262
|
throwOnError: true
|
|
2301
2263
|
});
|
|
2302
|
-
const loadedMatchIds = Object.fromEntries([...this.state.matches, ...(this.state.pendingMatches ?? []), ...this.state.
|
|
2264
|
+
const loadedMatchIds = Object.fromEntries([...this.state.matches, ...(this.state.pendingMatches ?? []), ...this.state.cachedMatches]?.map(d => [d.id, true]));
|
|
2303
2265
|
this.__store.batch(() => {
|
|
2304
2266
|
matches.forEach(match => {
|
|
2305
2267
|
if (!loadedMatchIds[match.id]) {
|
|
2306
2268
|
this.__store.setState(s => ({
|
|
2307
2269
|
...s,
|
|
2308
|
-
|
|
2270
|
+
cachedMatches: [...s.cachedMatches, match]
|
|
2309
2271
|
}));
|
|
2310
2272
|
}
|
|
2311
2273
|
});
|
|
@@ -2435,7 +2397,7 @@ function getInitialRouterState(location) {
|
|
|
2435
2397
|
location,
|
|
2436
2398
|
matches: [],
|
|
2437
2399
|
pendingMatches: [],
|
|
2438
|
-
|
|
2400
|
+
cachedMatches: [],
|
|
2439
2401
|
lastUpdated: Date.now()
|
|
2440
2402
|
};
|
|
2441
2403
|
}
|