@remix-run/router 1.13.1 → 1.14.0-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 +187 -0
- package/dist/index.d.ts +1 -1
- package/dist/router.cjs.js +117 -39
- package/dist/router.cjs.js.map +1 -1
- package/dist/router.d.ts +16 -0
- package/dist/router.js +109 -39
- package/dist/router.js.map +1 -1
- package/dist/router.umd.js +117 -39
- 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 +131 -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.1
|
|
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,12 +1380,28 @@ function createRouter(init) {
|
|
|
1366
1380
|
[route.id]: error
|
|
1367
1381
|
};
|
|
1368
1382
|
}
|
|
1369
|
-
let initialized
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1383
|
+
let initialized;
|
|
1384
|
+
let hasLazyRoutes = initialMatches.some(m => m.route.lazy);
|
|
1385
|
+
let hasLoaders = initialMatches.some(m => m.route.loader);
|
|
1386
|
+
if (hasLazyRoutes) {
|
|
1387
|
+
// All initialMatches need to be loaded before we're ready. If we have lazy
|
|
1388
|
+
// functions around still then we'll need to run them in initialize()
|
|
1389
|
+
initialized = false;
|
|
1390
|
+
} else if (!hasLoaders) {
|
|
1391
|
+
// If we've got no loaders to run, then we're good to go
|
|
1392
|
+
initialized = true;
|
|
1393
|
+
} else if (future.v7_partialHydration) {
|
|
1394
|
+
// If partial hydration is enabled, we're initialized so long as we were
|
|
1395
|
+
// provided with hydrationData for every route with a loader, and no loaders
|
|
1396
|
+
// were marked for explicit hydration
|
|
1397
|
+
let loaderData = init.hydrationData ? init.hydrationData.loaderData : null;
|
|
1398
|
+
let errors = init.hydrationData ? init.hydrationData.errors : null;
|
|
1399
|
+
initialized = initialMatches.every(m => m.route.loader && m.route.loader.hydrate !== true && (loaderData && loaderData[m.route.id] !== undefined || errors && errors[m.route.id] !== undefined));
|
|
1400
|
+
} else {
|
|
1401
|
+
// Without partial hydration - we're initialized if we were provided any
|
|
1402
|
+
// hydrationData - which is expected to be complete
|
|
1403
|
+
initialized = init.hydrationData != null;
|
|
1404
|
+
}
|
|
1375
1405
|
let router;
|
|
1376
1406
|
let state = {
|
|
1377
1407
|
historyAction: init.history.action,
|
|
@@ -1515,7 +1545,9 @@ function createRouter(init) {
|
|
|
1515
1545
|
// resolved prior to router creation since we can't go into a fallbackElement
|
|
1516
1546
|
// UI for SSR'd apps
|
|
1517
1547
|
if (!state.initialized) {
|
|
1518
|
-
startNavigation(Action.Pop, state.location
|
|
1548
|
+
startNavigation(Action.Pop, state.location, {
|
|
1549
|
+
initialHydration: true
|
|
1550
|
+
});
|
|
1519
1551
|
}
|
|
1520
1552
|
return router;
|
|
1521
1553
|
}
|
|
@@ -1690,7 +1722,7 @@ function createRouter(init) {
|
|
|
1690
1722
|
init.history.go(to);
|
|
1691
1723
|
return;
|
|
1692
1724
|
}
|
|
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);
|
|
1725
|
+
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
1726
|
let {
|
|
1695
1727
|
path,
|
|
1696
1728
|
submission,
|
|
@@ -1879,7 +1911,7 @@ function createRouter(init) {
|
|
|
1879
1911
|
shortCircuited,
|
|
1880
1912
|
loaderData,
|
|
1881
1913
|
errors
|
|
1882
|
-
} = await handleLoaders(request, location, matches, loadingNavigation, opts && opts.submission, opts && opts.fetcherSubmission, opts && opts.replace, flushSync, pendingActionData, pendingError);
|
|
1914
|
+
} = await handleLoaders(request, location, matches, loadingNavigation, opts && opts.submission, opts && opts.fetcherSubmission, opts && opts.replace, opts && opts.initialHydration === true, flushSync, pendingActionData, pendingError);
|
|
1883
1915
|
if (shortCircuited) {
|
|
1884
1916
|
return;
|
|
1885
1917
|
}
|
|
@@ -1923,7 +1955,7 @@ function createRouter(init) {
|
|
|
1923
1955
|
})
|
|
1924
1956
|
};
|
|
1925
1957
|
} else {
|
|
1926
|
-
result = await callLoaderOrAction("action", request, actionMatch, matches, manifest, mapRouteProperties, basename);
|
|
1958
|
+
result = await callLoaderOrAction("action", request, actionMatch, matches, manifest, mapRouteProperties, basename, future.v7_relativeSplatPath);
|
|
1927
1959
|
if (request.signal.aborted) {
|
|
1928
1960
|
return {
|
|
1929
1961
|
shortCircuited: true
|
|
@@ -1980,14 +2012,14 @@ function createRouter(init) {
|
|
|
1980
2012
|
}
|
|
1981
2013
|
// Call all applicable loaders for the given matches, handling redirects,
|
|
1982
2014
|
// errors, etc.
|
|
1983
|
-
async function handleLoaders(request, location, matches, overrideNavigation, submission, fetcherSubmission, replace, flushSync, pendingActionData, pendingError) {
|
|
2015
|
+
async function handleLoaders(request, location, matches, overrideNavigation, submission, fetcherSubmission, replace, initialHydration, flushSync, pendingActionData, pendingError) {
|
|
1984
2016
|
// Figure out the right navigation we want to use for data loading
|
|
1985
2017
|
let loadingNavigation = overrideNavigation || getLoadingNavigation(location, submission);
|
|
1986
2018
|
// If this was a redirect from an action we don't have a "submission" but
|
|
1987
2019
|
// we have it on the loading navigation so use that if available
|
|
1988
2020
|
let activeSubmission = submission || fetcherSubmission || getSubmissionFromNavigation(loadingNavigation);
|
|
1989
2021
|
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);
|
|
2022
|
+
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
2023
|
// Cancel pending deferreds for no-longer-matched routes or routes we're
|
|
1992
2024
|
// about to reload. Note that if this is an action reload we would have
|
|
1993
2025
|
// already cancelled all pending deferreds so this would be a no-op
|
|
@@ -2016,7 +2048,9 @@ function createRouter(init) {
|
|
|
2016
2048
|
// state. If not, we need to switch to our loading state and load data,
|
|
2017
2049
|
// preserving any new action data or existing action data (in the case of
|
|
2018
2050
|
// a revalidation interrupting an actionReload)
|
|
2019
|
-
|
|
2051
|
+
// If we have partialHydration enabled, then don't update the state for the
|
|
2052
|
+
// initial data load since iot's not a "navigation"
|
|
2053
|
+
if (!isUninterruptedRevalidation && (!future.v7_partialHydration || !initialHydration)) {
|
|
2020
2054
|
revalidatingFetchers.forEach(rf => {
|
|
2021
2055
|
let fetcher = state.fetchers.get(rf.key);
|
|
2022
2056
|
let revalidatingFetcher = getLoadingFetcher(undefined, fetcher ? fetcher.data : undefined);
|
|
@@ -2119,7 +2153,7 @@ function createRouter(init) {
|
|
|
2119
2153
|
if (fetchControllers.has(key)) abortFetcher(key);
|
|
2120
2154
|
let flushSync = (opts && opts.unstable_flushSync) === true;
|
|
2121
2155
|
let routesToUse = inFlightDataRoutes || dataRoutes;
|
|
2122
|
-
let normalizedPath = normalizeTo(state.location, state.matches, basename, future.v7_prependBasename, href, routeId, opts == null ? void 0 : opts.relative);
|
|
2156
|
+
let normalizedPath = normalizeTo(state.location, state.matches, basename, future.v7_prependBasename, href, future.v7_relativeSplatPath, routeId, opts == null ? void 0 : opts.relative);
|
|
2123
2157
|
let matches = matchRoutes(routesToUse, normalizedPath, basename);
|
|
2124
2158
|
if (!matches) {
|
|
2125
2159
|
setFetcherError(key, routeId, getInternalRouterError(404, {
|
|
@@ -2180,7 +2214,7 @@ function createRouter(init) {
|
|
|
2180
2214
|
let fetchRequest = createClientSideRequest(init.history, path, abortController.signal, submission);
|
|
2181
2215
|
fetchControllers.set(key, abortController);
|
|
2182
2216
|
let originatingLoadId = incrementingLoadId;
|
|
2183
|
-
let actionResult = await callLoaderOrAction("action", fetchRequest, match, requestMatches, manifest, mapRouteProperties, basename);
|
|
2217
|
+
let actionResult = await callLoaderOrAction("action", fetchRequest, match, requestMatches, manifest, mapRouteProperties, basename, future.v7_relativeSplatPath);
|
|
2184
2218
|
if (fetchRequest.signal.aborted) {
|
|
2185
2219
|
// We can delete this so long as we weren't aborted by our own fetcher
|
|
2186
2220
|
// re-submit which would have put _new_ controller is in fetchControllers
|
|
@@ -2231,7 +2265,7 @@ function createRouter(init) {
|
|
|
2231
2265
|
fetchReloadIds.set(key, loadId);
|
|
2232
2266
|
let loadFetcher = getLoadingFetcher(submission, actionResult.data);
|
|
2233
2267
|
state.fetchers.set(key, loadFetcher);
|
|
2234
|
-
let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, submission, nextLocation, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, deletedFetchers, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, {
|
|
2268
|
+
let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, submission, nextLocation, false, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, deletedFetchers, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, {
|
|
2235
2269
|
[match.route.id]: actionResult.data
|
|
2236
2270
|
}, undefined // No need to send through errors since we short circuit above
|
|
2237
2271
|
);
|
|
@@ -2325,7 +2359,7 @@ function createRouter(init) {
|
|
|
2325
2359
|
let fetchRequest = createClientSideRequest(init.history, path, abortController.signal);
|
|
2326
2360
|
fetchControllers.set(key, abortController);
|
|
2327
2361
|
let originatingLoadId = incrementingLoadId;
|
|
2328
|
-
let result = await callLoaderOrAction("loader", fetchRequest, match, matches, manifest, mapRouteProperties, basename);
|
|
2362
|
+
let result = await callLoaderOrAction("loader", fetchRequest, match, matches, manifest, mapRouteProperties, basename, future.v7_relativeSplatPath);
|
|
2329
2363
|
// Deferred isn't supported for fetcher loads, await everything and treat it
|
|
2330
2364
|
// as a normal load. resolveDeferredData will return undefined if this
|
|
2331
2365
|
// fetcher gets aborted, so we just leave result untouched and short circuit
|
|
@@ -2464,9 +2498,9 @@ function createRouter(init) {
|
|
|
2464
2498
|
// Call all navigation loaders and revalidating fetcher loaders in parallel,
|
|
2465
2499
|
// then slice off the results into separate arrays so we can handle them
|
|
2466
2500
|
// accordingly
|
|
2467
|
-
let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, manifest, mapRouteProperties, basename)), ...fetchersToLoad.map(f => {
|
|
2501
|
+
let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, manifest, mapRouteProperties, basename, future.v7_relativeSplatPath)), ...fetchersToLoad.map(f => {
|
|
2468
2502
|
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);
|
|
2503
|
+
return callLoaderOrAction("loader", createClientSideRequest(init.history, f.path, f.controller.signal), f.match, f.matches, manifest, mapRouteProperties, basename, future.v7_relativeSplatPath);
|
|
2470
2504
|
} else {
|
|
2471
2505
|
let error = {
|
|
2472
2506
|
type: ResultType.error,
|
|
@@ -2735,6 +2769,9 @@ function createRouter(init) {
|
|
|
2735
2769
|
get basename() {
|
|
2736
2770
|
return basename;
|
|
2737
2771
|
},
|
|
2772
|
+
get future() {
|
|
2773
|
+
return future;
|
|
2774
|
+
},
|
|
2738
2775
|
get state() {
|
|
2739
2776
|
return state;
|
|
2740
2777
|
},
|
|
@@ -2788,6 +2825,10 @@ function createStaticHandler(routes, opts) {
|
|
|
2788
2825
|
} else {
|
|
2789
2826
|
mapRouteProperties = defaultMapRouteProperties;
|
|
2790
2827
|
}
|
|
2828
|
+
// Config driven behavior flags
|
|
2829
|
+
let future = _extends({
|
|
2830
|
+
v7_relativeSplatPath: false
|
|
2831
|
+
}, opts ? opts.future : null);
|
|
2791
2832
|
let dataRoutes = convertRoutesToDataRoutes(routes, mapRouteProperties, undefined, manifest);
|
|
2792
2833
|
/**
|
|
2793
2834
|
* The query() method is intended for document requests, in which we want to
|
|
@@ -2997,7 +3038,7 @@ function createStaticHandler(routes, opts) {
|
|
|
2997
3038
|
error
|
|
2998
3039
|
};
|
|
2999
3040
|
} else {
|
|
3000
|
-
result = await callLoaderOrAction("action", request, actionMatch, matches, manifest, mapRouteProperties, basename, {
|
|
3041
|
+
result = await callLoaderOrAction("action", request, actionMatch, matches, manifest, mapRouteProperties, basename, future.v7_relativeSplatPath, {
|
|
3001
3042
|
isStaticRequest: true,
|
|
3002
3043
|
isRouteRequest,
|
|
3003
3044
|
requestContext
|
|
@@ -3112,7 +3153,7 @@ function createStaticHandler(routes, opts) {
|
|
|
3112
3153
|
activeDeferreds: null
|
|
3113
3154
|
};
|
|
3114
3155
|
}
|
|
3115
|
-
let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, manifest, mapRouteProperties, basename, {
|
|
3156
|
+
let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, manifest, mapRouteProperties, basename, future.v7_relativeSplatPath, {
|
|
3116
3157
|
isStaticRequest: true,
|
|
3117
3158
|
isRouteRequest,
|
|
3118
3159
|
requestContext
|
|
@@ -3162,7 +3203,7 @@ function getStaticContextFromError(routes, context, error) {
|
|
|
3162
3203
|
function isSubmissionNavigation(opts) {
|
|
3163
3204
|
return opts != null && ("formData" in opts && opts.formData != null || "body" in opts && opts.body !== undefined);
|
|
3164
3205
|
}
|
|
3165
|
-
function normalizeTo(location, matches, basename, prependBasename, to, fromRouteId, relative) {
|
|
3206
|
+
function normalizeTo(location, matches, basename, prependBasename, to, v7_relativeSplatPath, fromRouteId, relative) {
|
|
3166
3207
|
let contextualMatches;
|
|
3167
3208
|
let activeRouteMatch;
|
|
3168
3209
|
if (fromRouteId) {
|
|
@@ -3181,7 +3222,7 @@ function normalizeTo(location, matches, basename, prependBasename, to, fromRoute
|
|
|
3181
3222
|
activeRouteMatch = matches[matches.length - 1];
|
|
3182
3223
|
}
|
|
3183
3224
|
// Resolve the relative path
|
|
3184
|
-
let path = resolveTo(to ? to : ".",
|
|
3225
|
+
let path = resolveTo(to ? to : ".", getResolveToMatches(contextualMatches, v7_relativeSplatPath), stripBasename(location.pathname, basename) || location.pathname, relative === "path");
|
|
3185
3226
|
// When `to` is not specified we inherit search/hash from the current
|
|
3186
3227
|
// location, unlike when to="." and we just inherit the path.
|
|
3187
3228
|
// See https://github.com/remix-run/remix/issues/927
|
|
@@ -3338,7 +3379,7 @@ function getLoaderMatchesUntilBoundary(matches, boundaryId) {
|
|
|
3338
3379
|
}
|
|
3339
3380
|
return boundaryMatches;
|
|
3340
3381
|
}
|
|
3341
|
-
function getMatchesToLoad(history, state, matches, submission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, deletedFetchers, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, pendingActionData, pendingError) {
|
|
3382
|
+
function getMatchesToLoad(history, state, matches, submission, location, isInitialLoad, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, deletedFetchers, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, pendingActionData, pendingError) {
|
|
3342
3383
|
let actionResult = pendingError ? Object.values(pendingError)[0] : pendingActionData ? Object.values(pendingActionData)[0] : undefined;
|
|
3343
3384
|
let currentUrl = history.createURL(state.location);
|
|
3344
3385
|
let nextUrl = history.createURL(location);
|
|
@@ -3346,6 +3387,11 @@ function getMatchesToLoad(history, state, matches, submission, location, isReval
|
|
|
3346
3387
|
let boundaryId = pendingError ? Object.keys(pendingError)[0] : undefined;
|
|
3347
3388
|
let boundaryMatches = getLoaderMatchesUntilBoundary(matches, boundaryId);
|
|
3348
3389
|
let navigationMatches = boundaryMatches.filter((match, index) => {
|
|
3390
|
+
if (isInitialLoad) {
|
|
3391
|
+
// On initial hydration we don't do any shouldRevalidate stuff - we just
|
|
3392
|
+
// call the unhydrated loaders
|
|
3393
|
+
return isUnhydratedRoute(state, match.route);
|
|
3394
|
+
}
|
|
3349
3395
|
if (match.route.lazy) {
|
|
3350
3396
|
// We haven't loaded this route yet so we don't know if it's got a loader!
|
|
3351
3397
|
return true;
|
|
@@ -3382,8 +3428,12 @@ function getMatchesToLoad(history, state, matches, submission, location, isReval
|
|
|
3382
3428
|
// Pick fetcher.loads that need to be revalidated
|
|
3383
3429
|
let revalidatingFetchers = [];
|
|
3384
3430
|
fetchLoadMatches.forEach((f, key) => {
|
|
3385
|
-
// Don't revalidate
|
|
3386
|
-
|
|
3431
|
+
// Don't revalidate:
|
|
3432
|
+
// - on initial load (shouldn't be any fetchers then anyway)
|
|
3433
|
+
// - if fetcher won't be present in the subsequent render
|
|
3434
|
+
// - no longer matches the URL (v7_fetcherPersist=false)
|
|
3435
|
+
// - was unmounted but persisted due to v7_fetcherPersist=true
|
|
3436
|
+
if (isInitialLoad || !matches.some(m => m.route.id === f.routeId) || deletedFetchers.has(key)) {
|
|
3387
3437
|
return;
|
|
3388
3438
|
}
|
|
3389
3439
|
let fetcherMatches = matchRoutes(routesToUse, f.path, basename);
|
|
@@ -3445,6 +3495,19 @@ function getMatchesToLoad(history, state, matches, submission, location, isReval
|
|
|
3445
3495
|
});
|
|
3446
3496
|
return [navigationMatches, revalidatingFetchers];
|
|
3447
3497
|
}
|
|
3498
|
+
// Is this route unhydrated (when v7_partialHydration=true) such that we need
|
|
3499
|
+
// to call it's loader on the initial router creation
|
|
3500
|
+
function isUnhydratedRoute(state, route) {
|
|
3501
|
+
if (!route.loader) {
|
|
3502
|
+
return false;
|
|
3503
|
+
}
|
|
3504
|
+
if (route.loader.hydrate) {
|
|
3505
|
+
return true;
|
|
3506
|
+
}
|
|
3507
|
+
return state.loaderData[route.id] === undefined && (!state.errors ||
|
|
3508
|
+
// Loader ran but errored - don't re-run
|
|
3509
|
+
state.errors[route.id] === undefined);
|
|
3510
|
+
}
|
|
3448
3511
|
function isNewLoader(currentLoaderData, currentMatch, match) {
|
|
3449
3512
|
let isNew =
|
|
3450
3513
|
// [a] -> [a, b]
|
|
@@ -3524,7 +3587,7 @@ async function loadLazyRouteModule(route, mapRouteProperties, manifest) {
|
|
|
3524
3587
|
lazy: undefined
|
|
3525
3588
|
}));
|
|
3526
3589
|
}
|
|
3527
|
-
async function callLoaderOrAction(type, request, match, matches, manifest, mapRouteProperties, basename, opts) {
|
|
3590
|
+
async function callLoaderOrAction(type, request, match, matches, manifest, mapRouteProperties, basename, v7_relativeSplatPath, opts) {
|
|
3528
3591
|
if (opts === void 0) {
|
|
3529
3592
|
opts = {};
|
|
3530
3593
|
}
|
|
@@ -3612,7 +3675,7 @@ async function callLoaderOrAction(type, request, match, matches, manifest, mapRo
|
|
|
3612
3675
|
invariant(location, "Redirects returned/thrown from loaders/actions must have a Location header");
|
|
3613
3676
|
// Support relative routing in internal redirects
|
|
3614
3677
|
if (!ABSOLUTE_URL_REGEX.test(location)) {
|
|
3615
|
-
location = normalizeTo(new URL(request.url), matches.slice(0, matches.indexOf(match) + 1), basename, true, location);
|
|
3678
|
+
location = normalizeTo(new URL(request.url), matches.slice(0, matches.indexOf(match) + 1), basename, true, location, v7_relativeSplatPath);
|
|
3616
3679
|
} else if (!opts.isStaticRequest) {
|
|
3617
3680
|
// Strip off the protocol+origin for same-origin + same-basename absolute
|
|
3618
3681
|
// redirects. If this is a static request, we can let it go back to the
|
|
@@ -3651,13 +3714,20 @@ async function callLoaderOrAction(type, request, match, matches, manifest, mapRo
|
|
|
3651
3714
|
throw queryRouteResponse;
|
|
3652
3715
|
}
|
|
3653
3716
|
let data;
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3717
|
+
try {
|
|
3718
|
+
let contentType = result.headers.get("Content-Type");
|
|
3719
|
+
// Check between word boundaries instead of startsWith() due to the last
|
|
3720
|
+
// paragraph of https://httpwg.org/specs/rfc9110.html#field.content-type
|
|
3721
|
+
if (contentType && /\bapplication\/json\b/.test(contentType)) {
|
|
3722
|
+
data = await result.json();
|
|
3723
|
+
} else {
|
|
3724
|
+
data = await result.text();
|
|
3725
|
+
}
|
|
3726
|
+
} catch (e) {
|
|
3727
|
+
return {
|
|
3728
|
+
type: ResultType.error,
|
|
3729
|
+
error: e
|
|
3730
|
+
};
|
|
3661
3731
|
}
|
|
3662
3732
|
if (resultType === ResultType.error) {
|
|
3663
3733
|
return {
|
|
@@ -4233,5 +4303,5 @@ function persistAppliedTransitions(_window, transitions) {
|
|
|
4233
4303
|
}
|
|
4234
4304
|
//#endregion
|
|
4235
4305
|
|
|
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,
|
|
4306
|
+
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
4307
|
//# sourceMappingURL=router.js.map
|