@remix-run/router 0.0.0-experimental-e192105b → 0.0.0-experimental-178bc9ee
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 +28 -0
- package/dist/index.d.ts +2 -2
- package/dist/router.cjs.js +118 -89
- package/dist/router.cjs.js.map +1 -1
- package/dist/router.d.ts +9 -1
- package/dist/router.js +115 -88
- package/dist/router.js.map +1 -1
- package/dist/router.umd.js +118 -89
- 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 +2 -1
- package/index.ts +2 -1
- package/package.json +1 -1
- package/router.ts +147 -77
- package/utils.ts +35 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# `@remix-run/router`
|
|
2
2
|
|
|
3
|
+
## 1.12.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Add `unstable_flushSync` option to `router.navigate` and `router.fetch` to tell the React Router layer to opt-out of `React.startTransition` and into `ReactDOM.flushSync` for state updates ([#11005](https://github.com/remix-run/react-router/pull/11005))
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Fix `relative="path"` bug where relative path calculations started from the full location pathname, instead of from the current contextual route pathname. ([#11006](https://github.com/remix-run/react-router/pull/11006))
|
|
12
|
+
|
|
13
|
+
```jsx
|
|
14
|
+
<Route path="/a">
|
|
15
|
+
<Route path="/b" element={<Component />}>
|
|
16
|
+
<Route path="/c" />
|
|
17
|
+
</Route>
|
|
18
|
+
</Route>;
|
|
19
|
+
|
|
20
|
+
function Component() {
|
|
21
|
+
return (
|
|
22
|
+
<>
|
|
23
|
+
{/* This is now correctly relative to /a/b, not /a/b/c */}
|
|
24
|
+
<Link to=".." relative="path" />
|
|
25
|
+
<Outlet />
|
|
26
|
+
</>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
3
31
|
## 1.11.0
|
|
4
32
|
|
|
5
33
|
### Minor Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export type { ActionFunction, ActionFunctionArgs, AgnosticDataIndexRouteObject, AgnosticDataNonIndexRouteObject, AgnosticDataRouteMatch, AgnosticDataRouteObject, AgnosticIndexRouteObject, AgnosticNonIndexRouteObject, AgnosticRouteMatch, AgnosticRouteObject, ErrorResponse, FormEncType, FormMethod, HTMLFormMethod, JsonFunction, LazyRouteFunction, LoaderFunction, LoaderFunctionArgs, ParamParseKey, Params, PathMatch, PathPattern, RedirectFunction, ShouldRevalidateFunction, ShouldRevalidateFunctionArgs, TrackedPromise, UIMatch, V7_FormMethod, } from "./utils";
|
|
1
|
+
export type { ActionFunction, ActionFunctionArgs, AgnosticDataIndexRouteObject, AgnosticDataNonIndexRouteObject, AgnosticDataRouteMatch, AgnosticDataRouteObject, AgnosticIndexRouteObject, AgnosticNonIndexRouteObject, AgnosticRouteMatch, AgnosticRouteObject, ErrorResponse, FormEncType, FormMethod, HTMLFormMethod, JsonFunction, LazyRouteFunction, LoaderFunction, LoaderFunctionArgs, ParamParseKey, Params, PathMatch, PathParam, PathPattern, RedirectFunction, ShouldRevalidateFunction, ShouldRevalidateFunctionArgs, TrackedPromise, UIMatch, V7_FormMethod, } from "./utils";
|
|
2
2
|
export { AbortedDeferredError, defer, generatePath, getToPathname, isRouteErrorResponse, joinPaths, json, matchPath, matchRoutes, normalizePathname, redirect, redirectDocument, resolvePath, resolveTo, stripBasename, } from "./utils";
|
|
3
3
|
export type { BrowserHistory, BrowserHistoryOptions, HashHistory, HashHistoryOptions, History, InitialEntry, Location, MemoryHistory, MemoryHistoryOptions, Path, To, } from "./history";
|
|
4
4
|
export { Action, createBrowserHistory, createHashHistory, createMemoryHistory, createPath, parsePath, } from "./history";
|
|
5
5
|
export * from "./router";
|
|
6
6
|
/** @internal */
|
|
7
7
|
export type { RouteManifest as UNSAFE_RouteManifest } from "./utils";
|
|
8
|
-
export { DeferredData as UNSAFE_DeferredData, ErrorResponseImpl as UNSAFE_ErrorResponseImpl, convertRoutesToDataRoutes as UNSAFE_convertRoutesToDataRoutes, convertRouteMatchToUiMatch as UNSAFE_convertRouteMatchToUiMatch,
|
|
8
|
+
export { DeferredData as UNSAFE_DeferredData, ErrorResponseImpl as UNSAFE_ErrorResponseImpl, convertRoutesToDataRoutes as UNSAFE_convertRoutesToDataRoutes, convertRouteMatchToUiMatch as UNSAFE_convertRouteMatchToUiMatch, getResolveToMatches as UNSAFE_getResolveToMatches, } from "./utils";
|
|
9
9
|
export { invariant as UNSAFE_invariant, warning as UNSAFE_warning, } from "./history";
|
package/dist/router.cjs.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @remix-run/router v0.0.0-experimental-
|
|
2
|
+
* @remix-run/router v0.0.0-experimental-178bc9ee
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -1192,6 +1192,13 @@ function getPathContributingMatches(matches) {
|
|
|
1192
1192
|
return matches.filter((match, index) => index === 0 || match.route.path && match.route.path.length > 0);
|
|
1193
1193
|
}
|
|
1194
1194
|
|
|
1195
|
+
// Return the array of pathnames for the current route matches - used to
|
|
1196
|
+
// generate the routePathnames input for resolveTo()
|
|
1197
|
+
function getResolveToMatches(matches) {
|
|
1198
|
+
// Use the full pathname for the leaf match so we include splat values for "." links
|
|
1199
|
+
return getPathContributingMatches(matches).map((match, idx) => idx === matches.length - 1 ? match.pathname : match.pathnameBase);
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1195
1202
|
/**
|
|
1196
1203
|
* @private
|
|
1197
1204
|
*/
|
|
@@ -1221,16 +1228,30 @@ function resolveTo(toArg, routePathnames, locationPathname, isPathRelative) {
|
|
|
1221
1228
|
// `to` values that do not provide a pathname. `to` can simply be a search or
|
|
1222
1229
|
// hash string, in which case we should assume that the navigation is relative
|
|
1223
1230
|
// to the current location's pathname and *not* the route pathname.
|
|
1224
|
-
if (
|
|
1231
|
+
if (toPathname == null) {
|
|
1225
1232
|
from = locationPathname;
|
|
1233
|
+
} else if (isPathRelative) {
|
|
1234
|
+
let fromSegments = routePathnames[routePathnames.length - 1].replace(/^\//, "").split("/");
|
|
1235
|
+
if (toPathname.startsWith("..")) {
|
|
1236
|
+
let toSegments = toPathname.split("/");
|
|
1237
|
+
|
|
1238
|
+
// With relative="path", each leading .. segment means "go up one URL segment"
|
|
1239
|
+
while (toSegments[0] === "..") {
|
|
1240
|
+
toSegments.shift();
|
|
1241
|
+
fromSegments.pop();
|
|
1242
|
+
}
|
|
1243
|
+
to.pathname = toSegments.join("/");
|
|
1244
|
+
}
|
|
1245
|
+
from = "/" + fromSegments.join("/");
|
|
1226
1246
|
} else {
|
|
1227
1247
|
let routePathnameIndex = routePathnames.length - 1;
|
|
1228
1248
|
if (toPathname.startsWith("..")) {
|
|
1229
1249
|
let toSegments = toPathname.split("/");
|
|
1230
1250
|
|
|
1231
|
-
//
|
|
1232
|
-
// URL segment". This is a key
|
|
1233
|
-
//
|
|
1251
|
+
// With relative="route" (the default), each leading .. segment means
|
|
1252
|
+
// "go up one route" instead of "go up one URL segment". This is a key
|
|
1253
|
+
// difference from how <a href> works and a major reason we call this a
|
|
1254
|
+
// "to" value instead of a "href".
|
|
1234
1255
|
while (toSegments[0] === "..") {
|
|
1235
1256
|
toSegments.shift();
|
|
1236
1257
|
routePathnameIndex -= 1;
|
|
@@ -1665,6 +1686,7 @@ function createRouter(init) {
|
|
|
1665
1686
|
let future = _extends({
|
|
1666
1687
|
v7_fetcherPersist: false,
|
|
1667
1688
|
v7_normalizeFormMethod: false,
|
|
1689
|
+
v7_partialHydration: false,
|
|
1668
1690
|
v7_prependBasename: false
|
|
1669
1691
|
}, init.future);
|
|
1670
1692
|
// Cleanup function for history
|
|
@@ -1701,7 +1723,13 @@ function createRouter(init) {
|
|
|
1701
1723
|
[route.id]: error
|
|
1702
1724
|
};
|
|
1703
1725
|
}
|
|
1704
|
-
|
|
1726
|
+
|
|
1727
|
+
// "Initialized" here really means "Can `RouterProvider` render my route tree?"
|
|
1728
|
+
// Prior to `route.Fallback`, we only had a root `fallbackElement` so we used
|
|
1729
|
+
// `state.initialized` to render that instead of `<DataRoutes>`. Now that we
|
|
1730
|
+
// support route level fallbacks we can always render and we'll just render
|
|
1731
|
+
// as deep as we have data for and detect the nearest ancestor Fallback
|
|
1732
|
+
let initialized = future.v7_partialHydration ||
|
|
1705
1733
|
// All initialMatches need to be loaded before we're ready. If we have lazy
|
|
1706
1734
|
// functions around still then we'll need to run them in initialize()
|
|
1707
1735
|
!initialMatches.some(m => m.route.lazy) && (
|
|
@@ -1739,9 +1767,6 @@ function createRouter(init) {
|
|
|
1739
1767
|
// Should the current navigation enable document.startViewTransition?
|
|
1740
1768
|
let pendingViewTransitionEnabled = false;
|
|
1741
1769
|
|
|
1742
|
-
// Should the current navigation use flushSync for state updates?
|
|
1743
|
-
let pendingFlushSync = false;
|
|
1744
|
-
|
|
1745
1770
|
// Store applied view transitions so we can apply them on POP
|
|
1746
1771
|
let appliedViewTransitions = new Map();
|
|
1747
1772
|
|
|
@@ -1855,8 +1880,6 @@ function createRouter(init) {
|
|
|
1855
1880
|
blockers.set(blockerKey, IDLE_BLOCKER);
|
|
1856
1881
|
updateState({
|
|
1857
1882
|
blockers
|
|
1858
|
-
}, {
|
|
1859
|
-
flushSync: false
|
|
1860
1883
|
});
|
|
1861
1884
|
}
|
|
1862
1885
|
});
|
|
@@ -1878,8 +1901,10 @@ function createRouter(init) {
|
|
|
1878
1901
|
// in the normal navigation flow. For SSR it's expected that lazy modules are
|
|
1879
1902
|
// resolved prior to router creation since we can't go into a fallbackElement
|
|
1880
1903
|
// UI for SSR'd apps
|
|
1881
|
-
if (!state.initialized) {
|
|
1882
|
-
startNavigation(Action.Pop, state.location
|
|
1904
|
+
if (!state.initialized || future.v7_partialHydration && state.matches.some(m => m.route.loader && state.loaderData[m.route.id] === undefined)) {
|
|
1905
|
+
startNavigation(Action.Pop, state.location, {
|
|
1906
|
+
initialHydration: true
|
|
1907
|
+
});
|
|
1883
1908
|
}
|
|
1884
1909
|
return router;
|
|
1885
1910
|
}
|
|
@@ -1906,6 +1931,9 @@ function createRouter(init) {
|
|
|
1906
1931
|
|
|
1907
1932
|
// Update our state and notify the calling context of the change
|
|
1908
1933
|
function updateState(newState, opts) {
|
|
1934
|
+
if (opts === void 0) {
|
|
1935
|
+
opts = {};
|
|
1936
|
+
}
|
|
1909
1937
|
state = _extends({}, state, newState);
|
|
1910
1938
|
|
|
1911
1939
|
// Prep fetcher cleanup so we can tell the UI which fetcher data entries
|
|
@@ -1933,7 +1961,7 @@ function createRouter(init) {
|
|
|
1933
1961
|
[...subscribers].forEach(subscriber => subscriber(state, {
|
|
1934
1962
|
deletedFetchers: deletedFetchersKeys,
|
|
1935
1963
|
unstable_viewTransitionOpts: opts.viewTransitionOpts,
|
|
1936
|
-
unstable_flushSync: opts.flushSync
|
|
1964
|
+
unstable_flushSync: opts.flushSync === true
|
|
1937
1965
|
}));
|
|
1938
1966
|
|
|
1939
1967
|
// Remove idle fetchers from state since we only care about in-flight fetchers.
|
|
@@ -1948,8 +1976,11 @@ function createRouter(init) {
|
|
|
1948
1976
|
// - Location is a required param
|
|
1949
1977
|
// - Navigation will always be set to IDLE_NAVIGATION
|
|
1950
1978
|
// - Can pass any other state in newState
|
|
1951
|
-
function completeNavigation(location, newState) {
|
|
1979
|
+
function completeNavigation(location, newState, _temp) {
|
|
1952
1980
|
var _location$state, _location$state2;
|
|
1981
|
+
let {
|
|
1982
|
+
flushSync
|
|
1983
|
+
} = _temp === void 0 ? {} : _temp;
|
|
1953
1984
|
// Deduce if we're in a loading/actionReload state:
|
|
1954
1985
|
// - We have committed actionData in the store
|
|
1955
1986
|
// - The current navigation was a mutation submission
|
|
@@ -2042,14 +2073,13 @@ function createRouter(init) {
|
|
|
2042
2073
|
blockers
|
|
2043
2074
|
}), {
|
|
2044
2075
|
viewTransitionOpts,
|
|
2045
|
-
flushSync:
|
|
2076
|
+
flushSync: flushSync === true
|
|
2046
2077
|
});
|
|
2047
2078
|
|
|
2048
2079
|
// Reset stateful navigation vars
|
|
2049
2080
|
pendingAction = Action.Pop;
|
|
2050
2081
|
pendingPreventScrollReset = false;
|
|
2051
2082
|
pendingViewTransitionEnabled = false;
|
|
2052
|
-
pendingFlushSync = false;
|
|
2053
2083
|
isUninterruptedRevalidation = false;
|
|
2054
2084
|
isRevalidationRequired = false;
|
|
2055
2085
|
cancelledDeferredRoutes = [];
|
|
@@ -2116,8 +2146,6 @@ function createRouter(init) {
|
|
|
2116
2146
|
blockers.set(blockerKey, IDLE_BLOCKER);
|
|
2117
2147
|
updateState({
|
|
2118
2148
|
blockers
|
|
2119
|
-
}, {
|
|
2120
|
-
flushSync
|
|
2121
2149
|
});
|
|
2122
2150
|
}
|
|
2123
2151
|
});
|
|
@@ -2142,8 +2170,6 @@ function createRouter(init) {
|
|
|
2142
2170
|
interruptActiveLoads();
|
|
2143
2171
|
updateState({
|
|
2144
2172
|
revalidation: "loading"
|
|
2145
|
-
}, {
|
|
2146
|
-
flushSync: false
|
|
2147
2173
|
});
|
|
2148
2174
|
|
|
2149
2175
|
// If we're currently submitting an action, we don't need to start a new
|
|
@@ -2187,10 +2213,10 @@ function createRouter(init) {
|
|
|
2187
2213
|
saveScrollPosition(state.location, state.matches);
|
|
2188
2214
|
pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;
|
|
2189
2215
|
pendingViewTransitionEnabled = (opts && opts.enableViewTransition) === true;
|
|
2190
|
-
pendingFlushSync = (opts && opts.flushSync) === true;
|
|
2191
2216
|
let routesToUse = inFlightDataRoutes || dataRoutes;
|
|
2192
2217
|
let loadingNavigation = opts && opts.overrideNavigation;
|
|
2193
2218
|
let matches = matchRoutes(routesToUse, location, basename);
|
|
2219
|
+
let flushSync = (opts && opts.flushSync) === true;
|
|
2194
2220
|
|
|
2195
2221
|
// Short circuit with a 404 on the root error boundary if we match nothing
|
|
2196
2222
|
if (!matches) {
|
|
@@ -2209,6 +2235,8 @@ function createRouter(init) {
|
|
|
2209
2235
|
errors: {
|
|
2210
2236
|
[route.id]: error
|
|
2211
2237
|
}
|
|
2238
|
+
}, {
|
|
2239
|
+
flushSync
|
|
2212
2240
|
});
|
|
2213
2241
|
return;
|
|
2214
2242
|
}
|
|
@@ -2222,13 +2250,15 @@ function createRouter(init) {
|
|
|
2222
2250
|
if (state.initialized && !isRevalidationRequired && isHashChangeOnly(state.location, location) && !(opts && opts.submission && isMutationMethod(opts.submission.formMethod))) {
|
|
2223
2251
|
completeNavigation(location, {
|
|
2224
2252
|
matches
|
|
2253
|
+
}, {
|
|
2254
|
+
flushSync
|
|
2225
2255
|
});
|
|
2226
2256
|
return;
|
|
2227
2257
|
}
|
|
2228
2258
|
|
|
2229
2259
|
// Create a controller/Request for this navigation
|
|
2230
2260
|
pendingNavigationController = new AbortController();
|
|
2231
|
-
let request = createClientSideRequest(init.history, location, pendingNavigationController.signal, opts && opts.submission);
|
|
2261
|
+
let request = createClientSideRequest(init.history, location, pendingNavigationController.signal, opts && opts.initialHydration === true, opts && opts.submission);
|
|
2232
2262
|
let pendingActionData;
|
|
2233
2263
|
let pendingError;
|
|
2234
2264
|
if (opts && opts.pendingError) {
|
|
@@ -2242,7 +2272,8 @@ function createRouter(init) {
|
|
|
2242
2272
|
} else if (opts && opts.submission && isMutationMethod(opts.submission.formMethod)) {
|
|
2243
2273
|
// Call action if we received an action submission
|
|
2244
2274
|
let actionOutput = await handleAction(request, location, opts.submission, matches, {
|
|
2245
|
-
replace: opts.replace
|
|
2275
|
+
replace: opts.replace,
|
|
2276
|
+
flushSync
|
|
2246
2277
|
});
|
|
2247
2278
|
if (actionOutput.shortCircuited) {
|
|
2248
2279
|
return;
|
|
@@ -2250,6 +2281,7 @@ function createRouter(init) {
|
|
|
2250
2281
|
pendingActionData = actionOutput.pendingActionData;
|
|
2251
2282
|
pendingError = actionOutput.pendingActionError;
|
|
2252
2283
|
loadingNavigation = getLoadingNavigation(location, opts.submission);
|
|
2284
|
+
flushSync = false;
|
|
2253
2285
|
|
|
2254
2286
|
// Create a GET request for the loaders
|
|
2255
2287
|
request = new Request(request.url, {
|
|
@@ -2262,7 +2294,7 @@ function createRouter(init) {
|
|
|
2262
2294
|
shortCircuited,
|
|
2263
2295
|
loaderData,
|
|
2264
2296
|
errors
|
|
2265
|
-
} = await handleLoaders(request, location, matches, loadingNavigation, opts && opts.submission, opts && opts.fetcherSubmission, opts && opts.replace, pendingActionData, pendingError);
|
|
2297
|
+
} = await handleLoaders(request, location, matches, loadingNavigation, opts && opts.submission, opts && opts.fetcherSubmission, opts && opts.replace, opts && opts.initialHydration === true, flushSync, pendingActionData, pendingError);
|
|
2266
2298
|
if (shortCircuited) {
|
|
2267
2299
|
return;
|
|
2268
2300
|
}
|
|
@@ -2294,7 +2326,7 @@ function createRouter(init) {
|
|
|
2294
2326
|
updateState({
|
|
2295
2327
|
navigation
|
|
2296
2328
|
}, {
|
|
2297
|
-
flushSync:
|
|
2329
|
+
flushSync: opts.flushSync === true
|
|
2298
2330
|
});
|
|
2299
2331
|
|
|
2300
2332
|
// Call our action and get the result
|
|
@@ -2369,7 +2401,7 @@ function createRouter(init) {
|
|
|
2369
2401
|
|
|
2370
2402
|
// Call all applicable loaders for the given matches, handling redirects,
|
|
2371
2403
|
// errors, etc.
|
|
2372
|
-
async function handleLoaders(request, location, matches, overrideNavigation, submission, fetcherSubmission, replace, pendingActionData, pendingError) {
|
|
2404
|
+
async function handleLoaders(request, location, matches, overrideNavigation, submission, fetcherSubmission, replace, initialHydration, flushSync, pendingActionData, pendingError) {
|
|
2373
2405
|
// Figure out the right navigation we want to use for data loading
|
|
2374
2406
|
let loadingNavigation = overrideNavigation || getLoadingNavigation(location, submission);
|
|
2375
2407
|
|
|
@@ -2377,7 +2409,7 @@ function createRouter(init) {
|
|
|
2377
2409
|
// we have it on the loading navigation so use that if available
|
|
2378
2410
|
let activeSubmission = submission || fetcherSubmission || getSubmissionFromNavigation(loadingNavigation);
|
|
2379
2411
|
let routesToUse = inFlightDataRoutes || dataRoutes;
|
|
2380
|
-
let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, activeSubmission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, pendingActionData, pendingError);
|
|
2412
|
+
let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, activeSubmission, location, future.v7_partialHydration && initialHydration === true, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, deletedFetchers, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, pendingActionData, pendingError);
|
|
2381
2413
|
|
|
2382
2414
|
// Cancel pending deferreds for no-longer-matched routes or routes we're
|
|
2383
2415
|
// about to reload. Note that if this is an action reload we would have
|
|
@@ -2397,7 +2429,9 @@ function createRouter(init) {
|
|
|
2397
2429
|
actionData: pendingActionData
|
|
2398
2430
|
} : {}, updatedFetchers ? {
|
|
2399
2431
|
fetchers: new Map(state.fetchers)
|
|
2400
|
-
} : {})
|
|
2432
|
+
} : {}), {
|
|
2433
|
+
flushSync
|
|
2434
|
+
});
|
|
2401
2435
|
return {
|
|
2402
2436
|
shortCircuited: true
|
|
2403
2437
|
};
|
|
@@ -2423,7 +2457,7 @@ function createRouter(init) {
|
|
|
2423
2457
|
} : {}, revalidatingFetchers.length > 0 ? {
|
|
2424
2458
|
fetchers: new Map(state.fetchers)
|
|
2425
2459
|
} : {}), {
|
|
2426
|
-
flushSync
|
|
2460
|
+
flushSync
|
|
2427
2461
|
});
|
|
2428
2462
|
}
|
|
2429
2463
|
revalidatingFetchers.forEach(rf => {
|
|
@@ -2578,7 +2612,7 @@ function createRouter(init) {
|
|
|
2578
2612
|
|
|
2579
2613
|
// Call the action for the fetcher
|
|
2580
2614
|
let abortController = new AbortController();
|
|
2581
|
-
let fetchRequest = createClientSideRequest(init.history, path, abortController.signal, submission);
|
|
2615
|
+
let fetchRequest = createClientSideRequest(init.history, path, abortController.signal, false, submission);
|
|
2582
2616
|
fetchControllers.set(key, abortController);
|
|
2583
2617
|
let originatingLoadId = incrementingLoadId;
|
|
2584
2618
|
let actionResult = await callLoaderOrAction("action", fetchRequest, match, requestMatches, manifest, mapRouteProperties, basename);
|
|
@@ -2591,9 +2625,7 @@ function createRouter(init) {
|
|
|
2591
2625
|
return;
|
|
2592
2626
|
}
|
|
2593
2627
|
if (deletedFetchers.has(key)) {
|
|
2594
|
-
updateFetcherState(key, getDoneFetcher(undefined)
|
|
2595
|
-
flushSync
|
|
2596
|
-
});
|
|
2628
|
+
updateFetcherState(key, getDoneFetcher(undefined));
|
|
2597
2629
|
return;
|
|
2598
2630
|
}
|
|
2599
2631
|
if (isRedirectResult(actionResult)) {
|
|
@@ -2603,15 +2635,11 @@ function createRouter(init) {
|
|
|
2603
2635
|
// should take precedence over this redirect navigation. We already
|
|
2604
2636
|
// set isRevalidationRequired so all loaders for the new route should
|
|
2605
2637
|
// fire unless opted out via shouldRevalidate
|
|
2606
|
-
updateFetcherState(key, getDoneFetcher(undefined)
|
|
2607
|
-
flushSync
|
|
2608
|
-
});
|
|
2638
|
+
updateFetcherState(key, getDoneFetcher(undefined));
|
|
2609
2639
|
return;
|
|
2610
2640
|
} else {
|
|
2611
2641
|
fetchRedirectIds.add(key);
|
|
2612
|
-
updateFetcherState(key, getLoadingFetcher(submission)
|
|
2613
|
-
flushSync
|
|
2614
|
-
});
|
|
2642
|
+
updateFetcherState(key, getLoadingFetcher(submission));
|
|
2615
2643
|
return startRedirectNavigation(state, actionResult, {
|
|
2616
2644
|
fetcherSubmission: submission
|
|
2617
2645
|
});
|
|
@@ -2620,9 +2648,7 @@ function createRouter(init) {
|
|
|
2620
2648
|
|
|
2621
2649
|
// Process any non-redirect errors thrown
|
|
2622
2650
|
if (isErrorResult(actionResult)) {
|
|
2623
|
-
setFetcherError(key, routeId, actionResult.error
|
|
2624
|
-
flushSync
|
|
2625
|
-
});
|
|
2651
|
+
setFetcherError(key, routeId, actionResult.error);
|
|
2626
2652
|
return;
|
|
2627
2653
|
}
|
|
2628
2654
|
if (isDeferredResult(actionResult)) {
|
|
@@ -2634,7 +2660,7 @@ function createRouter(init) {
|
|
|
2634
2660
|
// Start the data load for current matches, or the next location if we're
|
|
2635
2661
|
// in the middle of a navigation
|
|
2636
2662
|
let nextLocation = state.navigation.location || state.location;
|
|
2637
|
-
let revalidationRequest = createClientSideRequest(init.history, nextLocation, abortController.signal);
|
|
2663
|
+
let revalidationRequest = createClientSideRequest(init.history, nextLocation, abortController.signal, false);
|
|
2638
2664
|
let routesToUse = inFlightDataRoutes || dataRoutes;
|
|
2639
2665
|
let matches = state.navigation.state !== "idle" ? matchRoutes(routesToUse, state.navigation.location, basename) : state.matches;
|
|
2640
2666
|
invariant(matches, "Didn't find any matches after fetcher action");
|
|
@@ -2642,7 +2668,7 @@ function createRouter(init) {
|
|
|
2642
2668
|
fetchReloadIds.set(key, loadId);
|
|
2643
2669
|
let loadFetcher = getLoadingFetcher(submission, actionResult.data);
|
|
2644
2670
|
state.fetchers.set(key, loadFetcher);
|
|
2645
|
-
let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, submission, nextLocation, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, {
|
|
2671
|
+
let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, submission, nextLocation, false, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, deletedFetchers, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, {
|
|
2646
2672
|
[match.route.id]: actionResult.data
|
|
2647
2673
|
}, undefined // No need to send through errors since we short circuit above
|
|
2648
2674
|
);
|
|
@@ -2664,8 +2690,6 @@ function createRouter(init) {
|
|
|
2664
2690
|
});
|
|
2665
2691
|
updateState({
|
|
2666
2692
|
fetchers: new Map(state.fetchers)
|
|
2667
|
-
}, {
|
|
2668
|
-
flushSync
|
|
2669
2693
|
});
|
|
2670
2694
|
let abortPendingFetchRevalidations = () => revalidatingFetchers.forEach(rf => abortFetcher(rf.key));
|
|
2671
2695
|
abortController.signal.addEventListener("abort", abortPendingFetchRevalidations);
|
|
@@ -2727,8 +2751,6 @@ function createRouter(init) {
|
|
|
2727
2751
|
errors,
|
|
2728
2752
|
loaderData: mergeLoaderData(state.loaderData, loaderData, matches, errors),
|
|
2729
2753
|
fetchers: new Map(state.fetchers)
|
|
2730
|
-
}, {
|
|
2731
|
-
flushSync
|
|
2732
2754
|
});
|
|
2733
2755
|
isRevalidationRequired = false;
|
|
2734
2756
|
}
|
|
@@ -2743,7 +2765,7 @@ function createRouter(init) {
|
|
|
2743
2765
|
|
|
2744
2766
|
// Call the loader for this fetcher route match
|
|
2745
2767
|
let abortController = new AbortController();
|
|
2746
|
-
let fetchRequest = createClientSideRequest(init.history, path, abortController.signal);
|
|
2768
|
+
let fetchRequest = createClientSideRequest(init.history, path, abortController.signal, false);
|
|
2747
2769
|
fetchControllers.set(key, abortController);
|
|
2748
2770
|
let originatingLoadId = incrementingLoadId;
|
|
2749
2771
|
let result = await callLoaderOrAction("loader", fetchRequest, match, matches, manifest, mapRouteProperties, basename);
|
|
@@ -2765,9 +2787,7 @@ function createRouter(init) {
|
|
|
2765
2787
|
return;
|
|
2766
2788
|
}
|
|
2767
2789
|
if (deletedFetchers.has(key)) {
|
|
2768
|
-
updateFetcherState(key, getDoneFetcher(undefined)
|
|
2769
|
-
flushSync
|
|
2770
|
-
});
|
|
2790
|
+
updateFetcherState(key, getDoneFetcher(undefined));
|
|
2771
2791
|
return;
|
|
2772
2792
|
}
|
|
2773
2793
|
|
|
@@ -2776,9 +2796,7 @@ function createRouter(init) {
|
|
|
2776
2796
|
if (pendingNavigationLoadId > originatingLoadId) {
|
|
2777
2797
|
// A new navigation was kicked off after our loader started, so that
|
|
2778
2798
|
// should take precedence over this redirect navigation
|
|
2779
|
-
updateFetcherState(key, getDoneFetcher(undefined)
|
|
2780
|
-
flushSync
|
|
2781
|
-
});
|
|
2799
|
+
updateFetcherState(key, getDoneFetcher(undefined));
|
|
2782
2800
|
return;
|
|
2783
2801
|
} else {
|
|
2784
2802
|
fetchRedirectIds.add(key);
|
|
@@ -2789,17 +2807,13 @@ function createRouter(init) {
|
|
|
2789
2807
|
|
|
2790
2808
|
// Process any non-redirect errors thrown
|
|
2791
2809
|
if (isErrorResult(result)) {
|
|
2792
|
-
setFetcherError(key, routeId, result.error
|
|
2793
|
-
flushSync
|
|
2794
|
-
});
|
|
2810
|
+
setFetcherError(key, routeId, result.error);
|
|
2795
2811
|
return;
|
|
2796
2812
|
}
|
|
2797
2813
|
invariant(!isDeferredResult(result), "Unhandled fetcher deferred data");
|
|
2798
2814
|
|
|
2799
2815
|
// Put the fetcher back into an idle state
|
|
2800
|
-
updateFetcherState(key, getDoneFetcher(result.data)
|
|
2801
|
-
flushSync
|
|
2802
|
-
});
|
|
2816
|
+
updateFetcherState(key, getDoneFetcher(result.data));
|
|
2803
2817
|
}
|
|
2804
2818
|
|
|
2805
2819
|
/**
|
|
@@ -2821,12 +2835,12 @@ function createRouter(init) {
|
|
|
2821
2835
|
* actually touch history until we've processed redirects, so we just use
|
|
2822
2836
|
* the history action from the original navigation (PUSH or REPLACE).
|
|
2823
2837
|
*/
|
|
2824
|
-
async function startRedirectNavigation(state, redirect,
|
|
2838
|
+
async function startRedirectNavigation(state, redirect, _temp2) {
|
|
2825
2839
|
let {
|
|
2826
2840
|
submission,
|
|
2827
2841
|
fetcherSubmission,
|
|
2828
2842
|
replace
|
|
2829
|
-
} =
|
|
2843
|
+
} = _temp2 === void 0 ? {} : _temp2;
|
|
2830
2844
|
if (redirect.revalidate) {
|
|
2831
2845
|
isRevalidationRequired = true;
|
|
2832
2846
|
}
|
|
@@ -2904,7 +2918,7 @@ function createRouter(init) {
|
|
|
2904
2918
|
// accordingly
|
|
2905
2919
|
let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, manifest, mapRouteProperties, basename)), ...fetchersToLoad.map(f => {
|
|
2906
2920
|
if (f.matches && f.match && f.controller) {
|
|
2907
|
-
return callLoaderOrAction("loader", createClientSideRequest(init.history, f.path, f.controller.signal), f.match, f.matches, manifest, mapRouteProperties, basename);
|
|
2921
|
+
return callLoaderOrAction("loader", createClientSideRequest(init.history, f.path, f.controller.signal, false), f.match, f.matches, manifest, mapRouteProperties, basename);
|
|
2908
2922
|
} else {
|
|
2909
2923
|
let error = {
|
|
2910
2924
|
type: ResultType.error,
|
|
@@ -2941,14 +2955,20 @@ function createRouter(init) {
|
|
|
2941
2955
|
});
|
|
2942
2956
|
}
|
|
2943
2957
|
function updateFetcherState(key, fetcher, opts) {
|
|
2958
|
+
if (opts === void 0) {
|
|
2959
|
+
opts = {};
|
|
2960
|
+
}
|
|
2944
2961
|
state.fetchers.set(key, fetcher);
|
|
2945
2962
|
updateState({
|
|
2946
2963
|
fetchers: new Map(state.fetchers)
|
|
2947
2964
|
}, {
|
|
2948
|
-
flushSync: opts.flushSync
|
|
2965
|
+
flushSync: (opts && opts.flushSync) === true
|
|
2949
2966
|
});
|
|
2950
2967
|
}
|
|
2951
2968
|
function setFetcherError(key, routeId, error, opts) {
|
|
2969
|
+
if (opts === void 0) {
|
|
2970
|
+
opts = {};
|
|
2971
|
+
}
|
|
2952
2972
|
let boundaryMatch = findNearestBoundary(state.matches, routeId);
|
|
2953
2973
|
deleteFetcher(key);
|
|
2954
2974
|
updateState({
|
|
@@ -2957,7 +2977,7 @@ function createRouter(init) {
|
|
|
2957
2977
|
},
|
|
2958
2978
|
fetchers: new Map(state.fetchers)
|
|
2959
2979
|
}, {
|
|
2960
|
-
flushSync: opts.flushSync
|
|
2980
|
+
flushSync: (opts && opts.flushSync) === true
|
|
2961
2981
|
});
|
|
2962
2982
|
}
|
|
2963
2983
|
function getFetcher(key) {
|
|
@@ -2999,8 +3019,6 @@ function createRouter(init) {
|
|
|
2999
3019
|
}
|
|
3000
3020
|
updateState({
|
|
3001
3021
|
fetchers: new Map(state.fetchers)
|
|
3002
|
-
}, {
|
|
3003
|
-
flushSync: false
|
|
3004
3022
|
});
|
|
3005
3023
|
}
|
|
3006
3024
|
function abortFetcher(key) {
|
|
@@ -3070,8 +3088,6 @@ function createRouter(init) {
|
|
|
3070
3088
|
blockers.set(key, newBlocker);
|
|
3071
3089
|
updateState({
|
|
3072
3090
|
blockers
|
|
3073
|
-
}, {
|
|
3074
|
-
flushSync: false
|
|
3075
3091
|
});
|
|
3076
3092
|
}
|
|
3077
3093
|
function shouldBlockNavigation(_ref2) {
|
|
@@ -3139,8 +3155,6 @@ function createRouter(init) {
|
|
|
3139
3155
|
if (y != null) {
|
|
3140
3156
|
updateState({
|
|
3141
3157
|
restoreScrollPosition: y
|
|
3142
|
-
}, {
|
|
3143
|
-
flushSync: false
|
|
3144
3158
|
});
|
|
3145
3159
|
}
|
|
3146
3160
|
}
|
|
@@ -3181,6 +3195,9 @@ function createRouter(init) {
|
|
|
3181
3195
|
get basename() {
|
|
3182
3196
|
return basename;
|
|
3183
3197
|
},
|
|
3198
|
+
get future() {
|
|
3199
|
+
return future;
|
|
3200
|
+
},
|
|
3184
3201
|
get state() {
|
|
3185
3202
|
return state;
|
|
3186
3203
|
},
|
|
@@ -3257,10 +3274,10 @@ function createStaticHandler(routes, opts) {
|
|
|
3257
3274
|
* propagate that out and return the raw Response so the HTTP server can
|
|
3258
3275
|
* return it directly.
|
|
3259
3276
|
*/
|
|
3260
|
-
async function query(request,
|
|
3277
|
+
async function query(request, _temp3) {
|
|
3261
3278
|
let {
|
|
3262
3279
|
requestContext
|
|
3263
|
-
} =
|
|
3280
|
+
} = _temp3 === void 0 ? {} : _temp3;
|
|
3264
3281
|
let url = new URL(request.url);
|
|
3265
3282
|
let method = request.method;
|
|
3266
3283
|
let location = createLocation("", createPath(url), null, "default");
|
|
@@ -3346,11 +3363,11 @@ function createStaticHandler(routes, opts) {
|
|
|
3346
3363
|
* code. Examples here are 404 and 405 errors that occur prior to reaching
|
|
3347
3364
|
* any user-defined loaders.
|
|
3348
3365
|
*/
|
|
3349
|
-
async function queryRoute(request,
|
|
3366
|
+
async function queryRoute(request, _temp4) {
|
|
3350
3367
|
let {
|
|
3351
3368
|
routeId,
|
|
3352
3369
|
requestContext
|
|
3353
|
-
} =
|
|
3370
|
+
} = _temp4 === void 0 ? {} : _temp4;
|
|
3354
3371
|
let url = new URL(request.url);
|
|
3355
3372
|
let method = request.method;
|
|
3356
3373
|
let location = createLocation("", createPath(url), null, "default");
|
|
@@ -3628,11 +3645,9 @@ function isSubmissionNavigation(opts) {
|
|
|
3628
3645
|
function normalizeTo(location, matches, basename, prependBasename, to, fromRouteId, relative) {
|
|
3629
3646
|
let contextualMatches;
|
|
3630
3647
|
let activeRouteMatch;
|
|
3631
|
-
if (fromRouteId
|
|
3648
|
+
if (fromRouteId) {
|
|
3632
3649
|
// Grab matches up to the calling route so our route-relative logic is
|
|
3633
|
-
// relative to the correct source route
|
|
3634
|
-
// fromRouteId is ignored since that is always relative to the current
|
|
3635
|
-
// location path
|
|
3650
|
+
// relative to the correct source route
|
|
3636
3651
|
contextualMatches = [];
|
|
3637
3652
|
for (let match of matches) {
|
|
3638
3653
|
contextualMatches.push(match);
|
|
@@ -3647,7 +3662,7 @@ function normalizeTo(location, matches, basename, prependBasename, to, fromRoute
|
|
|
3647
3662
|
}
|
|
3648
3663
|
|
|
3649
3664
|
// Resolve the relative path
|
|
3650
|
-
let path = resolveTo(to ? to : ".",
|
|
3665
|
+
let path = resolveTo(to ? to : ".", getResolveToMatches(contextualMatches), stripBasename(location.pathname, basename) || location.pathname, relative === "path");
|
|
3651
3666
|
|
|
3652
3667
|
// When `to` is not specified we inherit search/hash from the current
|
|
3653
3668
|
// location, unlike when to="." and we just inherit the path.
|
|
@@ -3811,7 +3826,7 @@ function getLoaderMatchesUntilBoundary(matches, boundaryId) {
|
|
|
3811
3826
|
}
|
|
3812
3827
|
return boundaryMatches;
|
|
3813
3828
|
}
|
|
3814
|
-
function getMatchesToLoad(history, state, matches, submission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, pendingActionData, pendingError) {
|
|
3829
|
+
function getMatchesToLoad(history, state, matches, submission, location, isInitialLoad, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, deletedFetchers, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, pendingActionData, pendingError) {
|
|
3815
3830
|
let actionResult = pendingError ? Object.values(pendingError)[0] : pendingActionData ? Object.values(pendingActionData)[0] : undefined;
|
|
3816
3831
|
let currentUrl = history.createURL(state.location);
|
|
3817
3832
|
let nextUrl = history.createURL(location);
|
|
@@ -3820,6 +3835,11 @@ function getMatchesToLoad(history, state, matches, submission, location, isReval
|
|
|
3820
3835
|
let boundaryId = pendingError ? Object.keys(pendingError)[0] : undefined;
|
|
3821
3836
|
let boundaryMatches = getLoaderMatchesUntilBoundary(matches, boundaryId);
|
|
3822
3837
|
let navigationMatches = boundaryMatches.filter((match, index) => {
|
|
3838
|
+
if (isInitialLoad) {
|
|
3839
|
+
// On initial hydration we don't do any shouldRevalidate stuff - we just
|
|
3840
|
+
// call the loaders that don't have hydration data
|
|
3841
|
+
return match.route.loader && state.loaderData[match.route.id] === undefined;
|
|
3842
|
+
}
|
|
3823
3843
|
if (match.route.lazy) {
|
|
3824
3844
|
// We haven't loaded this route yet so we don't know if it's got a loader!
|
|
3825
3845
|
return true;
|
|
@@ -3859,8 +3879,12 @@ function getMatchesToLoad(history, state, matches, submission, location, isReval
|
|
|
3859
3879
|
// Pick fetcher.loads that need to be revalidated
|
|
3860
3880
|
let revalidatingFetchers = [];
|
|
3861
3881
|
fetchLoadMatches.forEach((f, key) => {
|
|
3862
|
-
// Don't revalidate
|
|
3863
|
-
|
|
3882
|
+
// Don't revalidate:
|
|
3883
|
+
// - on initial load (shouldn't be any fetchers then anyway)
|
|
3884
|
+
// - if fetcher won't be present in the subsequent render
|
|
3885
|
+
// - no longer matches the URL (v7_fetcherPersist=false)
|
|
3886
|
+
// - was unmounted but persisted due to v7_fetcherPersist=true
|
|
3887
|
+
if (isInitialLoad || !matches.some(m => m.route.id === f.routeId) || deletedFetchers.has(key)) {
|
|
3864
3888
|
return;
|
|
3865
3889
|
}
|
|
3866
3890
|
let fetcherMatches = matchRoutes(routesToUse, f.path, basename);
|
|
@@ -4187,11 +4211,16 @@ async function callLoaderOrAction(type, request, match, matches, manifest, mapRo
|
|
|
4187
4211
|
// Utility method for creating the Request instances for loaders/actions during
|
|
4188
4212
|
// client-side navigations and fetches. During SSR we will always have a
|
|
4189
4213
|
// Request instance from the static handler (query/queryRoute)
|
|
4190
|
-
function createClientSideRequest(history, location, signal, submission) {
|
|
4214
|
+
function createClientSideRequest(history, location, signal, initial, submission) {
|
|
4191
4215
|
let url = history.createURL(stripHashFromPath(location)).toString();
|
|
4192
4216
|
let init = {
|
|
4193
4217
|
signal
|
|
4194
4218
|
};
|
|
4219
|
+
if (initial) {
|
|
4220
|
+
init.headers = {
|
|
4221
|
+
"X-Remix-Initial-Load": "yes"
|
|
4222
|
+
};
|
|
4223
|
+
}
|
|
4195
4224
|
if (submission && isMutationMethod(submission.formMethod)) {
|
|
4196
4225
|
let {
|
|
4197
4226
|
formMethod,
|
|
@@ -4399,13 +4428,13 @@ function getShortCircuitMatches(routes) {
|
|
|
4399
4428
|
route
|
|
4400
4429
|
};
|
|
4401
4430
|
}
|
|
4402
|
-
function getInternalRouterError(status,
|
|
4431
|
+
function getInternalRouterError(status, _temp5) {
|
|
4403
4432
|
let {
|
|
4404
4433
|
pathname,
|
|
4405
4434
|
routeId,
|
|
4406
4435
|
method,
|
|
4407
4436
|
type
|
|
4408
|
-
} =
|
|
4437
|
+
} = _temp5 === void 0 ? {} : _temp5;
|
|
4409
4438
|
let statusText = "Unknown Server Error";
|
|
4410
4439
|
let errorMessage = "Unknown @remix-run/router error";
|
|
4411
4440
|
if (status === 400) {
|
|
@@ -4746,7 +4775,7 @@ exports.UNSAFE_DeferredData = DeferredData;
|
|
|
4746
4775
|
exports.UNSAFE_ErrorResponseImpl = ErrorResponseImpl;
|
|
4747
4776
|
exports.UNSAFE_convertRouteMatchToUiMatch = convertRouteMatchToUiMatch;
|
|
4748
4777
|
exports.UNSAFE_convertRoutesToDataRoutes = convertRoutesToDataRoutes;
|
|
4749
|
-
exports.
|
|
4778
|
+
exports.UNSAFE_getResolveToMatches = getResolveToMatches;
|
|
4750
4779
|
exports.UNSAFE_invariant = invariant;
|
|
4751
4780
|
exports.UNSAFE_warning = warning;
|
|
4752
4781
|
exports.createBrowserHistory = createBrowserHistory;
|