@remix-run/router 1.7.1 → 1.7.2-pre.1
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/CHANGELOG.md +15 -0
- package/dist/router.cjs.js +104 -43
- package/dist/router.cjs.js.map +1 -1
- package/dist/router.js +103 -43
- package/dist/router.js.map +1 -1
- package/dist/router.umd.js +104 -43
- package/dist/router.umd.js.map +1 -1
- package/dist/router.umd.min.js +2 -2
- package/dist/router.umd.min.js.map +1 -1
- package/dist/utils.d.ts +4 -1
- package/package.json +1 -1
- package/router.ts +84 -37
- package/utils.ts +22 -3
package/dist/router.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @remix-run/router v1.7.1
|
|
2
|
+
* @remix-run/router v1.7.2-pre.1
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -1035,7 +1035,7 @@ class DeferredData {
|
|
|
1035
1035
|
this.pendingKeysSet.add(key);
|
|
1036
1036
|
// We store a little wrapper promise that will be extended with
|
|
1037
1037
|
// _data/_error props upon resolve/reject
|
|
1038
|
-
let promise = Promise.race([value, this.abortPromise]).then(data => this.onSettle(promise, key,
|
|
1038
|
+
let promise = Promise.race([value, this.abortPromise]).then(data => this.onSettle(promise, key, undefined, data), error => this.onSettle(promise, key, error));
|
|
1039
1039
|
// Register rejection listeners to avoid uncaught promise rejections on
|
|
1040
1040
|
// errors or aborted deferred values
|
|
1041
1041
|
promise.catch(() => {});
|
|
@@ -1057,7 +1057,17 @@ class DeferredData {
|
|
|
1057
1057
|
// Nothing left to abort!
|
|
1058
1058
|
this.unlistenAbortSignal();
|
|
1059
1059
|
}
|
|
1060
|
-
|
|
1060
|
+
// If the promise was resolved/rejected with undefined, we'll throw an error as you
|
|
1061
|
+
// should always resolve with a value or null
|
|
1062
|
+
if (error === undefined && data === undefined) {
|
|
1063
|
+
let undefinedError = new Error("Deferred data for key \"" + key + "\" resolved/rejected with `undefined`, " + "you must resolve/reject with a value or `null`.");
|
|
1064
|
+
Object.defineProperty(promise, "_error", {
|
|
1065
|
+
get: () => undefinedError
|
|
1066
|
+
});
|
|
1067
|
+
this.emit(false, key);
|
|
1068
|
+
return Promise.reject(undefinedError);
|
|
1069
|
+
}
|
|
1070
|
+
if (data === undefined) {
|
|
1061
1071
|
Object.defineProperty(promise, "_error", {
|
|
1062
1072
|
get: () => error
|
|
1063
1073
|
});
|
|
@@ -1809,6 +1819,7 @@ function createRouter(init) {
|
|
|
1809
1819
|
// about to reload. Note that if this is an action reload we would have
|
|
1810
1820
|
// already cancelled all pending deferreds so this would be a no-op
|
|
1811
1821
|
cancelActiveDeferreds(routeId => !(matches && matches.some(m => m.route.id === routeId)) || matchesToLoad && matchesToLoad.some(m => m.route.id === routeId));
|
|
1822
|
+
pendingNavigationLoadId = ++incrementingLoadId;
|
|
1812
1823
|
// Short circuit if we have no loaders to run
|
|
1813
1824
|
if (matchesToLoad.length === 0 && revalidatingFetchers.length === 0) {
|
|
1814
1825
|
let updatedFetchers = markFetchRedirectsDone();
|
|
@@ -1847,7 +1858,6 @@ function createRouter(init) {
|
|
|
1847
1858
|
fetchers: new Map(state.fetchers)
|
|
1848
1859
|
} : {}));
|
|
1849
1860
|
}
|
|
1850
|
-
pendingNavigationLoadId = ++incrementingLoadId;
|
|
1851
1861
|
revalidatingFetchers.forEach(rf => {
|
|
1852
1862
|
if (fetchControllers.has(rf.key)) {
|
|
1853
1863
|
abortFetcher(rf.key);
|
|
@@ -1884,7 +1894,14 @@ function createRouter(init) {
|
|
|
1884
1894
|
// If any loaders returned a redirect Response, start a new REPLACE navigation
|
|
1885
1895
|
let redirect = findRedirect(results);
|
|
1886
1896
|
if (redirect) {
|
|
1887
|
-
|
|
1897
|
+
if (redirect.idx >= matchesToLoad.length) {
|
|
1898
|
+
// If this redirect came from a fetcher make sure we mark it in
|
|
1899
|
+
// fetchRedirectIds so it doesn't get revalidated on the next set of
|
|
1900
|
+
// loader executions
|
|
1901
|
+
let fetcherKey = revalidatingFetchers[redirect.idx - matchesToLoad.length].key;
|
|
1902
|
+
fetchRedirectIds.add(fetcherKey);
|
|
1903
|
+
}
|
|
1904
|
+
await startRedirectNavigation(state, redirect.result, {
|
|
1888
1905
|
replace
|
|
1889
1906
|
});
|
|
1890
1907
|
return {
|
|
@@ -1983,6 +2000,7 @@ function createRouter(init) {
|
|
|
1983
2000
|
let abortController = new AbortController();
|
|
1984
2001
|
let fetchRequest = createClientSideRequest(init.history, path, abortController.signal, submission);
|
|
1985
2002
|
fetchControllers.set(key, abortController);
|
|
2003
|
+
let originatingLoadId = incrementingLoadId;
|
|
1986
2004
|
let actionResult = await callLoaderOrAction("action", fetchRequest, match, requestMatches, manifest, mapRouteProperties, basename);
|
|
1987
2005
|
if (fetchRequest.signal.aborted) {
|
|
1988
2006
|
// We can delete this so long as we weren't aborted by ou our own fetcher
|
|
@@ -1994,16 +2012,29 @@ function createRouter(init) {
|
|
|
1994
2012
|
}
|
|
1995
2013
|
if (isRedirectResult(actionResult)) {
|
|
1996
2014
|
fetchControllers.delete(key);
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2015
|
+
if (pendingNavigationLoadId > originatingLoadId) {
|
|
2016
|
+
// A new navigation was kicked off after our action started, so that
|
|
2017
|
+
// should take precedence over this redirect navigation. We already
|
|
2018
|
+
// set isRevalidationRequired so all loaders for the new route should
|
|
2019
|
+
// fire unless opted out via shouldRevalidate
|
|
2020
|
+
let doneFetcher = getDoneFetcher(undefined);
|
|
2021
|
+
state.fetchers.set(key, doneFetcher);
|
|
2022
|
+
updateState({
|
|
2023
|
+
fetchers: new Map(state.fetchers)
|
|
2024
|
+
});
|
|
2025
|
+
return;
|
|
2026
|
+
} else {
|
|
2027
|
+
fetchRedirectIds.add(key);
|
|
2028
|
+
let loadingFetcher = getLoadingFetcher(submission);
|
|
2029
|
+
state.fetchers.set(key, loadingFetcher);
|
|
2030
|
+
updateState({
|
|
2031
|
+
fetchers: new Map(state.fetchers)
|
|
2032
|
+
});
|
|
2033
|
+
return startRedirectNavigation(state, actionResult, {
|
|
2034
|
+
submission,
|
|
2035
|
+
isFetchActionRedirect: true
|
|
2036
|
+
});
|
|
2037
|
+
}
|
|
2007
2038
|
}
|
|
2008
2039
|
// Process any non-redirect errors thrown
|
|
2009
2040
|
if (isErrorResult(actionResult)) {
|
|
@@ -2064,7 +2095,14 @@ function createRouter(init) {
|
|
|
2064
2095
|
revalidatingFetchers.forEach(r => fetchControllers.delete(r.key));
|
|
2065
2096
|
let redirect = findRedirect(results);
|
|
2066
2097
|
if (redirect) {
|
|
2067
|
-
|
|
2098
|
+
if (redirect.idx >= matchesToLoad.length) {
|
|
2099
|
+
// If this redirect came from a fetcher make sure we mark it in
|
|
2100
|
+
// fetchRedirectIds so it doesn't get revalidated on the next set of
|
|
2101
|
+
// loader executions
|
|
2102
|
+
let fetcherKey = revalidatingFetchers[redirect.idx - matchesToLoad.length].key;
|
|
2103
|
+
fetchRedirectIds.add(fetcherKey);
|
|
2104
|
+
}
|
|
2105
|
+
return startRedirectNavigation(state, redirect.result);
|
|
2068
2106
|
}
|
|
2069
2107
|
// Process and commit output from loaders
|
|
2070
2108
|
let {
|
|
@@ -2116,6 +2154,7 @@ function createRouter(init) {
|
|
|
2116
2154
|
let abortController = new AbortController();
|
|
2117
2155
|
let fetchRequest = createClientSideRequest(init.history, path, abortController.signal);
|
|
2118
2156
|
fetchControllers.set(key, abortController);
|
|
2157
|
+
let originatingLoadId = incrementingLoadId;
|
|
2119
2158
|
let result = await callLoaderOrAction("loader", fetchRequest, match, matches, manifest, mapRouteProperties, basename);
|
|
2120
2159
|
// Deferred isn't supported for fetcher loads, await everything and treat it
|
|
2121
2160
|
// as a normal load. resolveDeferredData will return undefined if this
|
|
@@ -2134,9 +2173,20 @@ function createRouter(init) {
|
|
|
2134
2173
|
}
|
|
2135
2174
|
// If the loader threw a redirect Response, start a new REPLACE navigation
|
|
2136
2175
|
if (isRedirectResult(result)) {
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2176
|
+
if (pendingNavigationLoadId > originatingLoadId) {
|
|
2177
|
+
// A new navigation was kicked off after our loader started, so that
|
|
2178
|
+
// should take precedence over this redirect navigation
|
|
2179
|
+
let doneFetcher = getDoneFetcher(undefined);
|
|
2180
|
+
state.fetchers.set(key, doneFetcher);
|
|
2181
|
+
updateState({
|
|
2182
|
+
fetchers: new Map(state.fetchers)
|
|
2183
|
+
});
|
|
2184
|
+
return;
|
|
2185
|
+
} else {
|
|
2186
|
+
fetchRedirectIds.add(key);
|
|
2187
|
+
await startRedirectNavigation(state, result);
|
|
2188
|
+
return;
|
|
2189
|
+
}
|
|
2140
2190
|
}
|
|
2141
2191
|
// Process any non-redirect errors thrown
|
|
2142
2192
|
if (isErrorResult(result)) {
|
|
@@ -3129,7 +3179,9 @@ function getMatchesToLoad(history, state, matches, submission, location, isReval
|
|
|
3129
3179
|
}
|
|
3130
3180
|
let fetcherMatches = matchRoutes(routesToUse, f.path, basename);
|
|
3131
3181
|
// If the fetcher path no longer matches, push it in with null matches so
|
|
3132
|
-
// we can trigger a 404 in callLoadersAndMaybeResolveData
|
|
3182
|
+
// we can trigger a 404 in callLoadersAndMaybeResolveData. Note this is
|
|
3183
|
+
// currently only a use-case for Remix HMR where the route tree can change
|
|
3184
|
+
// at runtime and remove a route previously loaded via a fetcher
|
|
3133
3185
|
if (!fetcherMatches) {
|
|
3134
3186
|
revalidatingFetchers.push({
|
|
3135
3187
|
key,
|
|
@@ -3142,30 +3194,35 @@ function getMatchesToLoad(history, state, matches, submission, location, isReval
|
|
|
3142
3194
|
return;
|
|
3143
3195
|
}
|
|
3144
3196
|
// Revalidating fetchers are decoupled from the route matches since they
|
|
3145
|
-
// load from a static href. They
|
|
3146
|
-
//
|
|
3147
|
-
//
|
|
3148
|
-
// They automatically revalidate without even calling shouldRevalidate if:
|
|
3149
|
-
// - They were cancelled
|
|
3150
|
-
// - They're in the middle of their first load and therefore this is still
|
|
3151
|
-
// an initial load and not a revalidation
|
|
3152
|
-
//
|
|
3153
|
-
// If neither of those is true, then they _always_ check shouldRevalidate
|
|
3197
|
+
// load from a static href. They revalidate based on explicit revalidation
|
|
3198
|
+
// (submission, useRevalidator, or X-Remix-Revalidate)
|
|
3154
3199
|
let fetcher = state.fetchers.get(key);
|
|
3155
|
-
let isPerformingInitialLoad = fetcher && fetcher.state !== "idle" && fetcher.data === undefined &&
|
|
3156
|
-
// If a fetcher.load redirected then it'll be "loading" without any data
|
|
3157
|
-
// so ensure we're not processing the redirect from this fetcher
|
|
3158
|
-
!fetchRedirectIds.has(key);
|
|
3159
3200
|
let fetcherMatch = getTargetMatch(fetcherMatches, f.path);
|
|
3160
|
-
let shouldRevalidate =
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3201
|
+
let shouldRevalidate = false;
|
|
3202
|
+
if (fetchRedirectIds.has(key)) {
|
|
3203
|
+
// Never trigger a revalidation of an actively redirecting fetcher
|
|
3204
|
+
shouldRevalidate = false;
|
|
3205
|
+
} else if (cancelledFetcherLoads.includes(key)) {
|
|
3206
|
+
// Always revalidate if the fetcher was cancelled
|
|
3207
|
+
shouldRevalidate = true;
|
|
3208
|
+
} else if (fetcher && fetcher.state !== "idle" && fetcher.data === undefined) {
|
|
3209
|
+
// If the fetcher hasn't ever completed loading yet, then this isn't a
|
|
3210
|
+
// revalidation, it would just be a brand new load if an explicit
|
|
3211
|
+
// revalidation is required
|
|
3212
|
+
shouldRevalidate = isRevalidationRequired;
|
|
3213
|
+
} else {
|
|
3214
|
+
// Otherwise fall back on any user-defined shouldRevalidate, defaulting
|
|
3215
|
+
// to explicit revalidations only
|
|
3216
|
+
shouldRevalidate = shouldRevalidateLoader(fetcherMatch, _extends({
|
|
3217
|
+
currentUrl,
|
|
3218
|
+
currentParams: state.matches[state.matches.length - 1].params,
|
|
3219
|
+
nextUrl,
|
|
3220
|
+
nextParams: matches[matches.length - 1].params
|
|
3221
|
+
}, submission, {
|
|
3222
|
+
actionResult,
|
|
3223
|
+
defaultShouldRevalidate: isRevalidationRequired
|
|
3224
|
+
}));
|
|
3225
|
+
}
|
|
3169
3226
|
if (shouldRevalidate) {
|
|
3170
3227
|
revalidatingFetchers.push({
|
|
3171
3228
|
key,
|
|
@@ -3661,7 +3718,10 @@ function findRedirect(results) {
|
|
|
3661
3718
|
for (let i = results.length - 1; i >= 0; i--) {
|
|
3662
3719
|
let result = results[i];
|
|
3663
3720
|
if (isRedirectResult(result)) {
|
|
3664
|
-
return
|
|
3721
|
+
return {
|
|
3722
|
+
result,
|
|
3723
|
+
idx: i
|
|
3724
|
+
};
|
|
3665
3725
|
}
|
|
3666
3726
|
}
|
|
3667
3727
|
}
|