@remix-run/router 1.13.1 → 1.14.0-pre.0
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 +181 -0
- package/dist/index.d.ts +1 -1
- package/dist/router.cjs.js +103 -35
- package/dist/router.cjs.js.map +1 -1
- package/dist/router.d.ts +16 -0
- package/dist/router.js +94 -35
- package/dist/router.js.map +1 -1
- package/dist/router.umd.js +103 -35
- 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 +5 -2
- package/index.ts +1 -1
- package/package.json +1 -1
- package/router.ts +120 -21
- package/utils.ts +27 -5
package/dist/router.d.ts
CHANGED
|
@@ -12,6 +12,13 @@ export interface Router {
|
|
|
12
12
|
* Return the basename for the router
|
|
13
13
|
*/
|
|
14
14
|
get basename(): RouterInit["basename"];
|
|
15
|
+
/**
|
|
16
|
+
* @internal
|
|
17
|
+
* PRIVATE - DO NOT USE
|
|
18
|
+
*
|
|
19
|
+
* Return the future config for the router
|
|
20
|
+
*/
|
|
21
|
+
get future(): FutureConfig;
|
|
15
22
|
/**
|
|
16
23
|
* @internal
|
|
17
24
|
* PRIVATE - DO NOT USE
|
|
@@ -248,7 +255,9 @@ export type HydrationState = Partial<Pick<RouterState, "loaderData" | "actionDat
|
|
|
248
255
|
export interface FutureConfig {
|
|
249
256
|
v7_fetcherPersist: boolean;
|
|
250
257
|
v7_normalizeFormMethod: boolean;
|
|
258
|
+
v7_partialHydration: boolean;
|
|
251
259
|
v7_prependBasename: boolean;
|
|
260
|
+
v7_relativeSplatPath: boolean;
|
|
252
261
|
}
|
|
253
262
|
/**
|
|
254
263
|
* Initialization options for createRouter
|
|
@@ -473,6 +482,12 @@ export declare const IDLE_BLOCKER: BlockerUnblocked;
|
|
|
473
482
|
*/
|
|
474
483
|
export declare function createRouter(init: RouterInit): Router;
|
|
475
484
|
export declare const UNSAFE_DEFERRED_SYMBOL: unique symbol;
|
|
485
|
+
/**
|
|
486
|
+
* Future flags to toggle new feature behavior
|
|
487
|
+
*/
|
|
488
|
+
export interface StaticHandlerFutureConfig {
|
|
489
|
+
v7_relativeSplatPath: boolean;
|
|
490
|
+
}
|
|
476
491
|
export interface CreateStaticHandlerOptions {
|
|
477
492
|
basename?: string;
|
|
478
493
|
/**
|
|
@@ -480,6 +495,7 @@ export interface CreateStaticHandlerOptions {
|
|
|
480
495
|
*/
|
|
481
496
|
detectErrorBoundary?: DetectErrorBoundaryFunction;
|
|
482
497
|
mapRouteProperties?: MapRoutePropertiesFunction;
|
|
498
|
+
future?: Partial<StaticHandlerFutureConfig>;
|
|
483
499
|
}
|
|
484
500
|
export declare function createStaticHandler(routes: AgnosticRouteObject[], opts?: CreateStaticHandlerOptions): StaticHandler;
|
|
485
501
|
/**
|
package/dist/router.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @remix-run/router v1.
|
|
2
|
+
* @remix-run/router v1.14.0-pre.0
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -938,6 +938,18 @@ function getInvalidPathError(char, field, dest, path) {
|
|
|
938
938
|
function getPathContributingMatches(matches) {
|
|
939
939
|
return matches.filter((match, index) => index === 0 || match.route.path && match.route.path.length > 0);
|
|
940
940
|
}
|
|
941
|
+
// Return the array of pathnames for the current route matches - used to
|
|
942
|
+
// generate the routePathnames input for resolveTo()
|
|
943
|
+
function getResolveToMatches(matches, v7_relativeSplatPath) {
|
|
944
|
+
let pathMatches = getPathContributingMatches(matches);
|
|
945
|
+
// When v7_relativeSplatPath is enabled, use the full pathname for the leaf
|
|
946
|
+
// match so we include splat values for "." links. See:
|
|
947
|
+
// https://github.com/remix-run/react-router/issues/11052#issuecomment-1836589329
|
|
948
|
+
if (v7_relativeSplatPath) {
|
|
949
|
+
return pathMatches.map((match, idx) => idx === matches.length - 1 ? match.pathname : match.pathnameBase);
|
|
950
|
+
}
|
|
951
|
+
return pathMatches.map(match => match.pathnameBase);
|
|
952
|
+
}
|
|
941
953
|
/**
|
|
942
954
|
* @private
|
|
943
955
|
*/
|
|
@@ -969,7 +981,7 @@ function resolveTo(toArg, routePathnames, locationPathname, isPathRelative) {
|
|
|
969
981
|
if (toPathname == null) {
|
|
970
982
|
from = locationPathname;
|
|
971
983
|
} else if (isPathRelative) {
|
|
972
|
-
let fromSegments = routePathnames[routePathnames.length - 1].replace(/^\//, "").split("/");
|
|
984
|
+
let fromSegments = routePathnames.length === 0 ? [] : routePathnames[routePathnames.length - 1].replace(/^\//, "").split("/");
|
|
973
985
|
if (toPathname.startsWith("..")) {
|
|
974
986
|
let toSegments = toPathname.split("/");
|
|
975
987
|
// With relative="path", each leading .. segment means "go up one URL segment"
|
|
@@ -1330,7 +1342,9 @@ function createRouter(init) {
|
|
|
1330
1342
|
let future = _extends({
|
|
1331
1343
|
v7_fetcherPersist: false,
|
|
1332
1344
|
v7_normalizeFormMethod: false,
|
|
1333
|
-
|
|
1345
|
+
v7_partialHydration: false,
|
|
1346
|
+
v7_prependBasename: false,
|
|
1347
|
+
v7_relativeSplatPath: false
|
|
1334
1348
|
}, init.future);
|
|
1335
1349
|
// Cleanup function for history
|
|
1336
1350
|
let unlistenHistory = null;
|
|
@@ -1366,7 +1380,12 @@ function createRouter(init) {
|
|
|
1366
1380
|
[route.id]: error
|
|
1367
1381
|
};
|
|
1368
1382
|
}
|
|
1369
|
-
|
|
1383
|
+
// "Initialized" here really means "Can `RouterProvider` render my route tree?"
|
|
1384
|
+
// Prior to `route.HydrateFallback`, we only had a root `fallbackElement` so we used
|
|
1385
|
+
// `state.initialized` to render that instead of `<DataRoutes>`. Now that we
|
|
1386
|
+
// support route level fallbacks we can always render and we'll just render
|
|
1387
|
+
// as deep as we have data for and detect the nearest ancestor HydrateFallback
|
|
1388
|
+
let initialized = future.v7_partialHydration ||
|
|
1370
1389
|
// All initialMatches need to be loaded before we're ready. If we have lazy
|
|
1371
1390
|
// functions around still then we'll need to run them in initialize()
|
|
1372
1391
|
!initialMatches.some(m => m.route.lazy) && (
|
|
@@ -1514,8 +1533,10 @@ function createRouter(init) {
|
|
|
1514
1533
|
// in the normal navigation flow. For SSR it's expected that lazy modules are
|
|
1515
1534
|
// resolved prior to router creation since we can't go into a fallbackElement
|
|
1516
1535
|
// UI for SSR'd apps
|
|
1517
|
-
if (!state.initialized) {
|
|
1518
|
-
startNavigation(Action.Pop, state.location
|
|
1536
|
+
if (!state.initialized || future.v7_partialHydration && state.matches.some(m => isUnhydratedRoute(state, m.route))) {
|
|
1537
|
+
startNavigation(Action.Pop, state.location, {
|
|
1538
|
+
initialHydration: true
|
|
1539
|
+
});
|
|
1519
1540
|
}
|
|
1520
1541
|
return router;
|
|
1521
1542
|
}
|
|
@@ -1690,7 +1711,7 @@ function createRouter(init) {
|
|
|
1690
1711
|
init.history.go(to);
|
|
1691
1712
|
return;
|
|
1692
1713
|
}
|
|
1693
|
-
let normalizedPath = normalizeTo(state.location, state.matches, basename, future.v7_prependBasename, to, opts == null ? void 0 : opts.fromRouteId, opts == null ? void 0 : opts.relative);
|
|
1714
|
+
let normalizedPath = normalizeTo(state.location, state.matches, basename, future.v7_prependBasename, to, future.v7_relativeSplatPath, opts == null ? void 0 : opts.fromRouteId, opts == null ? void 0 : opts.relative);
|
|
1694
1715
|
let {
|
|
1695
1716
|
path,
|
|
1696
1717
|
submission,
|
|
@@ -1879,7 +1900,7 @@ function createRouter(init) {
|
|
|
1879
1900
|
shortCircuited,
|
|
1880
1901
|
loaderData,
|
|
1881
1902
|
errors
|
|
1882
|
-
} = await handleLoaders(request, location, matches, loadingNavigation, opts && opts.submission, opts && opts.fetcherSubmission, opts && opts.replace, flushSync, pendingActionData, pendingError);
|
|
1903
|
+
} = await handleLoaders(request, location, matches, loadingNavigation, opts && opts.submission, opts && opts.fetcherSubmission, opts && opts.replace, opts && opts.initialHydration === true, flushSync, pendingActionData, pendingError);
|
|
1883
1904
|
if (shortCircuited) {
|
|
1884
1905
|
return;
|
|
1885
1906
|
}
|
|
@@ -1923,7 +1944,7 @@ function createRouter(init) {
|
|
|
1923
1944
|
})
|
|
1924
1945
|
};
|
|
1925
1946
|
} else {
|
|
1926
|
-
result = await callLoaderOrAction("action", request, actionMatch, matches, manifest, mapRouteProperties, basename);
|
|
1947
|
+
result = await callLoaderOrAction("action", request, actionMatch, matches, manifest, mapRouteProperties, basename, future.v7_relativeSplatPath);
|
|
1927
1948
|
if (request.signal.aborted) {
|
|
1928
1949
|
return {
|
|
1929
1950
|
shortCircuited: true
|
|
@@ -1980,14 +2001,14 @@ function createRouter(init) {
|
|
|
1980
2001
|
}
|
|
1981
2002
|
// Call all applicable loaders for the given matches, handling redirects,
|
|
1982
2003
|
// errors, etc.
|
|
1983
|
-
async function handleLoaders(request, location, matches, overrideNavigation, submission, fetcherSubmission, replace, flushSync, pendingActionData, pendingError) {
|
|
2004
|
+
async function handleLoaders(request, location, matches, overrideNavigation, submission, fetcherSubmission, replace, initialHydration, flushSync, pendingActionData, pendingError) {
|
|
1984
2005
|
// Figure out the right navigation we want to use for data loading
|
|
1985
2006
|
let loadingNavigation = overrideNavigation || getLoadingNavigation(location, submission);
|
|
1986
2007
|
// If this was a redirect from an action we don't have a "submission" but
|
|
1987
2008
|
// we have it on the loading navigation so use that if available
|
|
1988
2009
|
let activeSubmission = submission || fetcherSubmission || getSubmissionFromNavigation(loadingNavigation);
|
|
1989
2010
|
let routesToUse = inFlightDataRoutes || dataRoutes;
|
|
1990
|
-
let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, activeSubmission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, deletedFetchers, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, pendingActionData, pendingError);
|
|
2011
|
+
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);
|
|
1991
2012
|
// Cancel pending deferreds for no-longer-matched routes or routes we're
|
|
1992
2013
|
// about to reload. Note that if this is an action reload we would have
|
|
1993
2014
|
// already cancelled all pending deferreds so this would be a no-op
|
|
@@ -2016,7 +2037,9 @@ function createRouter(init) {
|
|
|
2016
2037
|
// state. If not, we need to switch to our loading state and load data,
|
|
2017
2038
|
// preserving any new action data or existing action data (in the case of
|
|
2018
2039
|
// a revalidation interrupting an actionReload)
|
|
2019
|
-
|
|
2040
|
+
// If we have partialHydration enabled, then don't update the state for the
|
|
2041
|
+
// initial data load since iot's not a "navigation"
|
|
2042
|
+
if (!isUninterruptedRevalidation && (!future.v7_partialHydration || !initialHydration)) {
|
|
2020
2043
|
revalidatingFetchers.forEach(rf => {
|
|
2021
2044
|
let fetcher = state.fetchers.get(rf.key);
|
|
2022
2045
|
let revalidatingFetcher = getLoadingFetcher(undefined, fetcher ? fetcher.data : undefined);
|
|
@@ -2119,7 +2142,7 @@ function createRouter(init) {
|
|
|
2119
2142
|
if (fetchControllers.has(key)) abortFetcher(key);
|
|
2120
2143
|
let flushSync = (opts && opts.unstable_flushSync) === true;
|
|
2121
2144
|
let routesToUse = inFlightDataRoutes || dataRoutes;
|
|
2122
|
-
let normalizedPath = normalizeTo(state.location, state.matches, basename, future.v7_prependBasename, href, routeId, opts == null ? void 0 : opts.relative);
|
|
2145
|
+
let normalizedPath = normalizeTo(state.location, state.matches, basename, future.v7_prependBasename, href, future.v7_relativeSplatPath, routeId, opts == null ? void 0 : opts.relative);
|
|
2123
2146
|
let matches = matchRoutes(routesToUse, normalizedPath, basename);
|
|
2124
2147
|
if (!matches) {
|
|
2125
2148
|
setFetcherError(key, routeId, getInternalRouterError(404, {
|
|
@@ -2180,7 +2203,7 @@ function createRouter(init) {
|
|
|
2180
2203
|
let fetchRequest = createClientSideRequest(init.history, path, abortController.signal, submission);
|
|
2181
2204
|
fetchControllers.set(key, abortController);
|
|
2182
2205
|
let originatingLoadId = incrementingLoadId;
|
|
2183
|
-
let actionResult = await callLoaderOrAction("action", fetchRequest, match, requestMatches, manifest, mapRouteProperties, basename);
|
|
2206
|
+
let actionResult = await callLoaderOrAction("action", fetchRequest, match, requestMatches, manifest, mapRouteProperties, basename, future.v7_relativeSplatPath);
|
|
2184
2207
|
if (fetchRequest.signal.aborted) {
|
|
2185
2208
|
// We can delete this so long as we weren't aborted by our own fetcher
|
|
2186
2209
|
// re-submit which would have put _new_ controller is in fetchControllers
|
|
@@ -2231,7 +2254,7 @@ function createRouter(init) {
|
|
|
2231
2254
|
fetchReloadIds.set(key, loadId);
|
|
2232
2255
|
let loadFetcher = getLoadingFetcher(submission, actionResult.data);
|
|
2233
2256
|
state.fetchers.set(key, loadFetcher);
|
|
2234
|
-
let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, submission, nextLocation, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, deletedFetchers, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, {
|
|
2257
|
+
let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, submission, nextLocation, false, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, deletedFetchers, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, {
|
|
2235
2258
|
[match.route.id]: actionResult.data
|
|
2236
2259
|
}, undefined // No need to send through errors since we short circuit above
|
|
2237
2260
|
);
|
|
@@ -2325,7 +2348,7 @@ function createRouter(init) {
|
|
|
2325
2348
|
let fetchRequest = createClientSideRequest(init.history, path, abortController.signal);
|
|
2326
2349
|
fetchControllers.set(key, abortController);
|
|
2327
2350
|
let originatingLoadId = incrementingLoadId;
|
|
2328
|
-
let result = await callLoaderOrAction("loader", fetchRequest, match, matches, manifest, mapRouteProperties, basename);
|
|
2351
|
+
let result = await callLoaderOrAction("loader", fetchRequest, match, matches, manifest, mapRouteProperties, basename, future.v7_relativeSplatPath);
|
|
2329
2352
|
// Deferred isn't supported for fetcher loads, await everything and treat it
|
|
2330
2353
|
// as a normal load. resolveDeferredData will return undefined if this
|
|
2331
2354
|
// fetcher gets aborted, so we just leave result untouched and short circuit
|
|
@@ -2464,9 +2487,9 @@ function createRouter(init) {
|
|
|
2464
2487
|
// Call all navigation loaders and revalidating fetcher loaders in parallel,
|
|
2465
2488
|
// then slice off the results into separate arrays so we can handle them
|
|
2466
2489
|
// accordingly
|
|
2467
|
-
let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, manifest, mapRouteProperties, basename)), ...fetchersToLoad.map(f => {
|
|
2490
|
+
let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, manifest, mapRouteProperties, basename, future.v7_relativeSplatPath)), ...fetchersToLoad.map(f => {
|
|
2468
2491
|
if (f.matches && f.match && f.controller) {
|
|
2469
|
-
return callLoaderOrAction("loader", createClientSideRequest(init.history, f.path, f.controller.signal), f.match, f.matches, manifest, mapRouteProperties, basename);
|
|
2492
|
+
return callLoaderOrAction("loader", createClientSideRequest(init.history, f.path, f.controller.signal), f.match, f.matches, manifest, mapRouteProperties, basename, future.v7_relativeSplatPath);
|
|
2470
2493
|
} else {
|
|
2471
2494
|
let error = {
|
|
2472
2495
|
type: ResultType.error,
|
|
@@ -2735,6 +2758,9 @@ function createRouter(init) {
|
|
|
2735
2758
|
get basename() {
|
|
2736
2759
|
return basename;
|
|
2737
2760
|
},
|
|
2761
|
+
get future() {
|
|
2762
|
+
return future;
|
|
2763
|
+
},
|
|
2738
2764
|
get state() {
|
|
2739
2765
|
return state;
|
|
2740
2766
|
},
|
|
@@ -2788,6 +2814,10 @@ function createStaticHandler(routes, opts) {
|
|
|
2788
2814
|
} else {
|
|
2789
2815
|
mapRouteProperties = defaultMapRouteProperties;
|
|
2790
2816
|
}
|
|
2817
|
+
// Config driven behavior flags
|
|
2818
|
+
let future = _extends({
|
|
2819
|
+
v7_relativeSplatPath: false
|
|
2820
|
+
}, opts ? opts.future : null);
|
|
2791
2821
|
let dataRoutes = convertRoutesToDataRoutes(routes, mapRouteProperties, undefined, manifest);
|
|
2792
2822
|
/**
|
|
2793
2823
|
* The query() method is intended for document requests, in which we want to
|
|
@@ -2997,7 +3027,7 @@ function createStaticHandler(routes, opts) {
|
|
|
2997
3027
|
error
|
|
2998
3028
|
};
|
|
2999
3029
|
} else {
|
|
3000
|
-
result = await callLoaderOrAction("action", request, actionMatch, matches, manifest, mapRouteProperties, basename, {
|
|
3030
|
+
result = await callLoaderOrAction("action", request, actionMatch, matches, manifest, mapRouteProperties, basename, future.v7_relativeSplatPath, {
|
|
3001
3031
|
isStaticRequest: true,
|
|
3002
3032
|
isRouteRequest,
|
|
3003
3033
|
requestContext
|
|
@@ -3112,7 +3142,7 @@ function createStaticHandler(routes, opts) {
|
|
|
3112
3142
|
activeDeferreds: null
|
|
3113
3143
|
};
|
|
3114
3144
|
}
|
|
3115
|
-
let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, manifest, mapRouteProperties, basename, {
|
|
3145
|
+
let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, manifest, mapRouteProperties, basename, future.v7_relativeSplatPath, {
|
|
3116
3146
|
isStaticRequest: true,
|
|
3117
3147
|
isRouteRequest,
|
|
3118
3148
|
requestContext
|
|
@@ -3162,7 +3192,7 @@ function getStaticContextFromError(routes, context, error) {
|
|
|
3162
3192
|
function isSubmissionNavigation(opts) {
|
|
3163
3193
|
return opts != null && ("formData" in opts && opts.formData != null || "body" in opts && opts.body !== undefined);
|
|
3164
3194
|
}
|
|
3165
|
-
function normalizeTo(location, matches, basename, prependBasename, to, fromRouteId, relative) {
|
|
3195
|
+
function normalizeTo(location, matches, basename, prependBasename, to, v7_relativeSplatPath, fromRouteId, relative) {
|
|
3166
3196
|
let contextualMatches;
|
|
3167
3197
|
let activeRouteMatch;
|
|
3168
3198
|
if (fromRouteId) {
|
|
@@ -3181,7 +3211,7 @@ function normalizeTo(location, matches, basename, prependBasename, to, fromRoute
|
|
|
3181
3211
|
activeRouteMatch = matches[matches.length - 1];
|
|
3182
3212
|
}
|
|
3183
3213
|
// Resolve the relative path
|
|
3184
|
-
let path = resolveTo(to ? to : ".",
|
|
3214
|
+
let path = resolveTo(to ? to : ".", getResolveToMatches(contextualMatches, v7_relativeSplatPath), stripBasename(location.pathname, basename) || location.pathname, relative === "path");
|
|
3185
3215
|
// When `to` is not specified we inherit search/hash from the current
|
|
3186
3216
|
// location, unlike when to="." and we just inherit the path.
|
|
3187
3217
|
// See https://github.com/remix-run/remix/issues/927
|
|
@@ -3338,7 +3368,7 @@ function getLoaderMatchesUntilBoundary(matches, boundaryId) {
|
|
|
3338
3368
|
}
|
|
3339
3369
|
return boundaryMatches;
|
|
3340
3370
|
}
|
|
3341
|
-
function getMatchesToLoad(history, state, matches, submission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, deletedFetchers, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, pendingActionData, pendingError) {
|
|
3371
|
+
function getMatchesToLoad(history, state, matches, submission, location, isInitialLoad, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, deletedFetchers, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, pendingActionData, pendingError) {
|
|
3342
3372
|
let actionResult = pendingError ? Object.values(pendingError)[0] : pendingActionData ? Object.values(pendingActionData)[0] : undefined;
|
|
3343
3373
|
let currentUrl = history.createURL(state.location);
|
|
3344
3374
|
let nextUrl = history.createURL(location);
|
|
@@ -3346,6 +3376,11 @@ function getMatchesToLoad(history, state, matches, submission, location, isReval
|
|
|
3346
3376
|
let boundaryId = pendingError ? Object.keys(pendingError)[0] : undefined;
|
|
3347
3377
|
let boundaryMatches = getLoaderMatchesUntilBoundary(matches, boundaryId);
|
|
3348
3378
|
let navigationMatches = boundaryMatches.filter((match, index) => {
|
|
3379
|
+
if (isInitialLoad) {
|
|
3380
|
+
// On initial hydration we don't do any shouldRevalidate stuff - we just
|
|
3381
|
+
// call the unhydrated loaders
|
|
3382
|
+
return isUnhydratedRoute(state, match.route);
|
|
3383
|
+
}
|
|
3349
3384
|
if (match.route.lazy) {
|
|
3350
3385
|
// We haven't loaded this route yet so we don't know if it's got a loader!
|
|
3351
3386
|
return true;
|
|
@@ -3382,8 +3417,12 @@ function getMatchesToLoad(history, state, matches, submission, location, isReval
|
|
|
3382
3417
|
// Pick fetcher.loads that need to be revalidated
|
|
3383
3418
|
let revalidatingFetchers = [];
|
|
3384
3419
|
fetchLoadMatches.forEach((f, key) => {
|
|
3385
|
-
// Don't revalidate
|
|
3386
|
-
|
|
3420
|
+
// Don't revalidate:
|
|
3421
|
+
// - on initial load (shouldn't be any fetchers then anyway)
|
|
3422
|
+
// - if fetcher won't be present in the subsequent render
|
|
3423
|
+
// - no longer matches the URL (v7_fetcherPersist=false)
|
|
3424
|
+
// - was unmounted but persisted due to v7_fetcherPersist=true
|
|
3425
|
+
if (isInitialLoad || !matches.some(m => m.route.id === f.routeId) || deletedFetchers.has(key)) {
|
|
3387
3426
|
return;
|
|
3388
3427
|
}
|
|
3389
3428
|
let fetcherMatches = matchRoutes(routesToUse, f.path, basename);
|
|
@@ -3445,6 +3484,19 @@ function getMatchesToLoad(history, state, matches, submission, location, isReval
|
|
|
3445
3484
|
});
|
|
3446
3485
|
return [navigationMatches, revalidatingFetchers];
|
|
3447
3486
|
}
|
|
3487
|
+
// Is this route unhydrated (when v7_partialHydration=true) such that we need
|
|
3488
|
+
// to call it's loader on the initial router creation
|
|
3489
|
+
function isUnhydratedRoute(state, route) {
|
|
3490
|
+
if (!route.loader) {
|
|
3491
|
+
return false;
|
|
3492
|
+
}
|
|
3493
|
+
if (route.loader.hydrate) {
|
|
3494
|
+
return true;
|
|
3495
|
+
}
|
|
3496
|
+
return state.loaderData[route.id] === undefined && (!state.errors ||
|
|
3497
|
+
// Loader ran but errored - don't re-run
|
|
3498
|
+
state.errors[route.id] === undefined);
|
|
3499
|
+
}
|
|
3448
3500
|
function isNewLoader(currentLoaderData, currentMatch, match) {
|
|
3449
3501
|
let isNew =
|
|
3450
3502
|
// [a] -> [a, b]
|
|
@@ -3524,7 +3576,7 @@ async function loadLazyRouteModule(route, mapRouteProperties, manifest) {
|
|
|
3524
3576
|
lazy: undefined
|
|
3525
3577
|
}));
|
|
3526
3578
|
}
|
|
3527
|
-
async function callLoaderOrAction(type, request, match, matches, manifest, mapRouteProperties, basename, opts) {
|
|
3579
|
+
async function callLoaderOrAction(type, request, match, matches, manifest, mapRouteProperties, basename, v7_relativeSplatPath, opts) {
|
|
3528
3580
|
if (opts === void 0) {
|
|
3529
3581
|
opts = {};
|
|
3530
3582
|
}
|
|
@@ -3612,7 +3664,7 @@ async function callLoaderOrAction(type, request, match, matches, manifest, mapRo
|
|
|
3612
3664
|
invariant(location, "Redirects returned/thrown from loaders/actions must have a Location header");
|
|
3613
3665
|
// Support relative routing in internal redirects
|
|
3614
3666
|
if (!ABSOLUTE_URL_REGEX.test(location)) {
|
|
3615
|
-
location = normalizeTo(new URL(request.url), matches.slice(0, matches.indexOf(match) + 1), basename, true, location);
|
|
3667
|
+
location = normalizeTo(new URL(request.url), matches.slice(0, matches.indexOf(match) + 1), basename, true, location, v7_relativeSplatPath);
|
|
3616
3668
|
} else if (!opts.isStaticRequest) {
|
|
3617
3669
|
// Strip off the protocol+origin for same-origin + same-basename absolute
|
|
3618
3670
|
// redirects. If this is a static request, we can let it go back to the
|
|
@@ -3651,13 +3703,20 @@ async function callLoaderOrAction(type, request, match, matches, manifest, mapRo
|
|
|
3651
3703
|
throw queryRouteResponse;
|
|
3652
3704
|
}
|
|
3653
3705
|
let data;
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3706
|
+
try {
|
|
3707
|
+
let contentType = result.headers.get("Content-Type");
|
|
3708
|
+
// Check between word boundaries instead of startsWith() due to the last
|
|
3709
|
+
// paragraph of https://httpwg.org/specs/rfc9110.html#field.content-type
|
|
3710
|
+
if (contentType && /\bapplication\/json\b/.test(contentType)) {
|
|
3711
|
+
data = await result.json();
|
|
3712
|
+
} else {
|
|
3713
|
+
data = await result.text();
|
|
3714
|
+
}
|
|
3715
|
+
} catch (e) {
|
|
3716
|
+
return {
|
|
3717
|
+
type: ResultType.error,
|
|
3718
|
+
error: e
|
|
3719
|
+
};
|
|
3661
3720
|
}
|
|
3662
3721
|
if (resultType === ResultType.error) {
|
|
3663
3722
|
return {
|
|
@@ -4233,5 +4292,5 @@ function persistAppliedTransitions(_window, transitions) {
|
|
|
4233
4292
|
}
|
|
4234
4293
|
//#endregion
|
|
4235
4294
|
|
|
4236
|
-
export { AbortedDeferredError, Action, IDLE_BLOCKER, IDLE_FETCHER, IDLE_NAVIGATION, UNSAFE_DEFERRED_SYMBOL, DeferredData as UNSAFE_DeferredData, ErrorResponseImpl as UNSAFE_ErrorResponseImpl, convertRouteMatchToUiMatch as UNSAFE_convertRouteMatchToUiMatch, convertRoutesToDataRoutes as UNSAFE_convertRoutesToDataRoutes,
|
|
4295
|
+
export { AbortedDeferredError, Action, IDLE_BLOCKER, IDLE_FETCHER, IDLE_NAVIGATION, UNSAFE_DEFERRED_SYMBOL, DeferredData as UNSAFE_DeferredData, ErrorResponseImpl as UNSAFE_ErrorResponseImpl, convertRouteMatchToUiMatch as UNSAFE_convertRouteMatchToUiMatch, convertRoutesToDataRoutes as UNSAFE_convertRoutesToDataRoutes, getResolveToMatches as UNSAFE_getResolveToMatches, invariant as UNSAFE_invariant, warning as UNSAFE_warning, createBrowserHistory, createHashHistory, createMemoryHistory, createPath, createRouter, createStaticHandler, defer, generatePath, getStaticContextFromError, getToPathname, isDeferredData, isRouteErrorResponse, joinPaths, json, matchPath, matchRoutes, normalizePathname, parsePath, redirect, redirectDocument, resolvePath, resolveTo, stripBasename };
|
|
4237
4296
|
//# sourceMappingURL=router.js.map
|