@remix-run/router 1.0.0 → 1.0.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 +9 -2
- package/dist/router.cjs.js +65 -76
- package/dist/router.cjs.js.map +1 -1
- package/dist/router.js +65 -76
- package/dist/router.js.map +1 -1
- package/history.ts +12 -8
- package/package.json +1 -1
- package/router.ts +76 -51
- package/utils.ts +5 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
#
|
|
1
|
+
# `@remix-run/router`
|
|
2
|
+
|
|
3
|
+
## 1.0.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Preserve state from `initialEntries` ([#9288](https://github.com/remix-run/react-router/pull/9288))
|
|
8
|
+
- Preserve `?index` for fetcher get submissions to index routes ([#9312](https://github.com/remix-run/react-router/pull/9312))
|
|
2
9
|
|
|
3
10
|
## 1.0.0
|
|
4
11
|
|
|
@@ -6,7 +13,7 @@ This is the first stable release of `@remix-run/router`, which provides all the
|
|
|
6
13
|
|
|
7
14
|
For an overview of the features provided by `react-router`, we recommend you go check out the [docs][rr-docs], especially the [feature overview][rr-feature-overview] and the [tutorial][rr-tutorial].
|
|
8
15
|
|
|
9
|
-
For an overview of the features provided by `@remix-run/router`, please check out the [README][remix-router-readme].
|
|
16
|
+
For an overview of the features provided by `@remix-run/router`, please check out the [`README`][remix-router-readme].
|
|
10
17
|
|
|
11
18
|
[rr-docs]: https://reactrouter.com/
|
|
12
19
|
[rr-feature-overview]: https://reactrouter.com/en/v6.4.0/start/overview
|
package/dist/router.cjs.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @remix-run/router v1.0.
|
|
2
|
+
* @remix-run/router v1.0.1
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -73,7 +73,7 @@ function createMemoryHistory(options) {
|
|
|
73
73
|
} = options;
|
|
74
74
|
let entries; // Declare so we can access from createMemoryLocation
|
|
75
75
|
|
|
76
|
-
entries = initialEntries.map((entry, index) => createMemoryLocation(entry, null, index === 0 ? "default" : undefined));
|
|
76
|
+
entries = initialEntries.map((entry, index) => createMemoryLocation(entry, typeof entry === "string" ? null : entry.state, index === 0 ? "default" : undefined));
|
|
77
77
|
let index = clampIndex(initialIndex == null ? entries.length - 1 : initialIndex);
|
|
78
78
|
let action = exports.Action.Pop;
|
|
79
79
|
let listener = null;
|
|
@@ -187,8 +187,6 @@ function createBrowserHistory(options) {
|
|
|
187
187
|
}
|
|
188
188
|
|
|
189
189
|
function createBrowserLocation(window, globalHistory) {
|
|
190
|
-
var _globalHistory$state, _globalHistory$state2;
|
|
191
|
-
|
|
192
190
|
let {
|
|
193
191
|
pathname,
|
|
194
192
|
search,
|
|
@@ -199,7 +197,7 @@ function createBrowserHistory(options) {
|
|
|
199
197
|
search,
|
|
200
198
|
hash
|
|
201
199
|
}, // state defaults to `null` because `window.history.state` does
|
|
202
|
-
|
|
200
|
+
globalHistory.state && globalHistory.state.usr || null, globalHistory.state && globalHistory.state.key || "default");
|
|
203
201
|
}
|
|
204
202
|
|
|
205
203
|
function createBrowserHref(window, to) {
|
|
@@ -238,8 +236,6 @@ function createHashHistory(options) {
|
|
|
238
236
|
}
|
|
239
237
|
|
|
240
238
|
function createHashLocation(window, globalHistory) {
|
|
241
|
-
var _globalHistory$state3, _globalHistory$state4;
|
|
242
|
-
|
|
243
239
|
let {
|
|
244
240
|
pathname = "/",
|
|
245
241
|
search = "",
|
|
@@ -250,7 +246,7 @@ function createHashHistory(options) {
|
|
|
250
246
|
search,
|
|
251
247
|
hash
|
|
252
248
|
}, // state defaults to `null` because `window.history.state` does
|
|
253
|
-
|
|
249
|
+
globalHistory.state && globalHistory.state.usr || null, globalHistory.state && globalHistory.state.key || "default");
|
|
254
250
|
}
|
|
255
251
|
|
|
256
252
|
function createHashHref(window, to) {
|
|
@@ -326,7 +322,7 @@ function createLocation(current, to, state, key) {
|
|
|
326
322
|
// full Locations now and avoid the need to run through this flow at all
|
|
327
323
|
// But that's a pretty big refactor to the current test suite so going to
|
|
328
324
|
// keep as is for the time being and just let any incoming keys take precedence
|
|
329
|
-
key:
|
|
325
|
+
key: to && to.key || key || createKey()
|
|
330
326
|
});
|
|
331
327
|
|
|
332
328
|
return location;
|
|
@@ -402,7 +398,7 @@ function getUrlBasedHistory(getLocation, createHref, validateLocation, options)
|
|
|
402
398
|
function push(to, state) {
|
|
403
399
|
action = exports.Action.Push;
|
|
404
400
|
let location = createLocation(history.location, to, state);
|
|
405
|
-
validateLocation
|
|
401
|
+
if (validateLocation) validateLocation(location, to);
|
|
406
402
|
let historyState = getHistoryState(location);
|
|
407
403
|
let url = history.createHref(location); // try...catch because iOS limits us to 100 pushState calls :/
|
|
408
404
|
|
|
@@ -425,7 +421,7 @@ function getUrlBasedHistory(getLocation, createHref, validateLocation, options)
|
|
|
425
421
|
function replace(to, state) {
|
|
426
422
|
action = exports.Action.Replace;
|
|
427
423
|
let location = createLocation(history.location, to, state);
|
|
428
|
-
validateLocation
|
|
424
|
+
if (validateLocation) validateLocation(location, to);
|
|
429
425
|
let historyState = getHistoryState(location);
|
|
430
426
|
let url = history.createHref(location);
|
|
431
427
|
globalHistory.replaceState(historyState, "", url);
|
|
@@ -1031,8 +1027,6 @@ class DeferredData {
|
|
|
1031
1027
|
}
|
|
1032
1028
|
|
|
1033
1029
|
onSettle(promise, key, error, data) {
|
|
1034
|
-
var _this$subscriber2;
|
|
1035
|
-
|
|
1036
1030
|
if (this.controller.signal.aborted && error instanceof AbortedDeferredError) {
|
|
1037
1031
|
this.unlistenAbortSignal();
|
|
1038
1032
|
Object.defineProperty(promise, "_error", {
|
|
@@ -1048,20 +1042,20 @@ class DeferredData {
|
|
|
1048
1042
|
this.unlistenAbortSignal();
|
|
1049
1043
|
}
|
|
1050
1044
|
|
|
1051
|
-
|
|
1052
|
-
var _this$subscriber;
|
|
1045
|
+
const subscriber = this.subscriber;
|
|
1053
1046
|
|
|
1047
|
+
if (error) {
|
|
1054
1048
|
Object.defineProperty(promise, "_error", {
|
|
1055
1049
|
get: () => error
|
|
1056
1050
|
});
|
|
1057
|
-
|
|
1051
|
+
subscriber && subscriber(false);
|
|
1058
1052
|
return Promise.reject(error);
|
|
1059
1053
|
}
|
|
1060
1054
|
|
|
1061
1055
|
Object.defineProperty(promise, "_data", {
|
|
1062
1056
|
get: () => data
|
|
1063
1057
|
});
|
|
1064
|
-
|
|
1058
|
+
subscriber && subscriber(false);
|
|
1065
1059
|
return data;
|
|
1066
1060
|
}
|
|
1067
1061
|
|
|
@@ -1070,11 +1064,10 @@ class DeferredData {
|
|
|
1070
1064
|
}
|
|
1071
1065
|
|
|
1072
1066
|
cancel() {
|
|
1073
|
-
var _this$subscriber3;
|
|
1074
|
-
|
|
1075
1067
|
this.controller.abort();
|
|
1076
1068
|
this.pendingKeys.forEach((v, k) => this.pendingKeys.delete(k));
|
|
1077
|
-
|
|
1069
|
+
let subscriber = this.subscriber;
|
|
1070
|
+
subscriber && subscriber(true);
|
|
1078
1071
|
}
|
|
1079
1072
|
|
|
1080
1073
|
async resolveData(signal) {
|
|
@@ -1213,8 +1206,6 @@ const IDLE_FETCHER = {
|
|
|
1213
1206
|
*/
|
|
1214
1207
|
|
|
1215
1208
|
function createRouter(init) {
|
|
1216
|
-
var _init$hydrationData, _init$hydrationData2, _init$hydrationData3;
|
|
1217
|
-
|
|
1218
1209
|
invariant(init.routes.length > 0, "You must provide a non-empty routes array to createRouter");
|
|
1219
1210
|
let dataRoutes = convertRoutesToDataRoutes(init.routes); // Cleanup function for history
|
|
1220
1211
|
|
|
@@ -1260,9 +1251,9 @@ function createRouter(init) {
|
|
|
1260
1251
|
restoreScrollPosition: null,
|
|
1261
1252
|
preventScrollReset: false,
|
|
1262
1253
|
revalidation: "idle",
|
|
1263
|
-
loaderData:
|
|
1264
|
-
actionData:
|
|
1265
|
-
errors:
|
|
1254
|
+
loaderData: init.hydrationData && init.hydrationData.loaderData || {},
|
|
1255
|
+
actionData: init.hydrationData && init.hydrationData.actionData || null,
|
|
1256
|
+
errors: init.hydrationData && init.hydrationData.errors || initialErrors,
|
|
1266
1257
|
fetchers: new Map()
|
|
1267
1258
|
}; // -- Stateful internal variables to manage navigations --
|
|
1268
1259
|
// Current navigation in progress (to be committed in completeNavigation)
|
|
@@ -1329,14 +1320,12 @@ function createRouter(init) {
|
|
|
1329
1320
|
|
|
1330
1321
|
|
|
1331
1322
|
function dispose() {
|
|
1332
|
-
var _pendingNavigationCon;
|
|
1333
|
-
|
|
1334
1323
|
if (unlistenHistory) {
|
|
1335
1324
|
unlistenHistory();
|
|
1336
1325
|
}
|
|
1337
1326
|
|
|
1338
1327
|
subscribers.clear();
|
|
1339
|
-
|
|
1328
|
+
pendingNavigationController && pendingNavigationController.abort();
|
|
1340
1329
|
state.fetchers.forEach((_, key) => deleteFetcher(key));
|
|
1341
1330
|
} // Subscribe to state updates for the router
|
|
1342
1331
|
|
|
@@ -1412,8 +1401,8 @@ function createRouter(init) {
|
|
|
1412
1401
|
submission,
|
|
1413
1402
|
error
|
|
1414
1403
|
} = normalizeNavigateOptions(to, opts);
|
|
1415
|
-
let location = createLocation(state.location, path, opts
|
|
1416
|
-
let historyAction = (opts
|
|
1404
|
+
let location = createLocation(state.location, path, opts && opts.state);
|
|
1405
|
+
let historyAction = (opts && opts.replace) === true || submission != null ? exports.Action.Replace : exports.Action.Push;
|
|
1417
1406
|
let preventScrollReset = opts && "preventScrollReset" in opts ? opts.preventScrollReset === true : undefined;
|
|
1418
1407
|
return await startNavigation(historyAction, location, {
|
|
1419
1408
|
submission,
|
|
@@ -1421,7 +1410,7 @@ function createRouter(init) {
|
|
|
1421
1410
|
// render at the right error boundary after we match routes
|
|
1422
1411
|
pendingError: error,
|
|
1423
1412
|
preventScrollReset,
|
|
1424
|
-
replace: opts
|
|
1413
|
+
replace: opts && opts.replace
|
|
1425
1414
|
});
|
|
1426
1415
|
} // Revalidate all current loaders. If a navigation is in progress or if this
|
|
1427
1416
|
// is interrupted by a navigation, allow this to "succeed" by calling all
|
|
@@ -1461,20 +1450,18 @@ function createRouter(init) {
|
|
|
1461
1450
|
|
|
1462
1451
|
|
|
1463
1452
|
async function startNavigation(historyAction, location, opts) {
|
|
1464
|
-
var _pendingNavigationCon2;
|
|
1465
|
-
|
|
1466
1453
|
// Abort any in-progress navigations and start a new one. Unset any ongoing
|
|
1467
1454
|
// uninterrupted revalidations unless told otherwise, since we want this
|
|
1468
1455
|
// new navigation to update history normally
|
|
1469
|
-
|
|
1456
|
+
pendingNavigationController && pendingNavigationController.abort();
|
|
1470
1457
|
pendingNavigationController = null;
|
|
1471
1458
|
pendingAction = historyAction;
|
|
1472
|
-
isUninterruptedRevalidation = (opts
|
|
1459
|
+
isUninterruptedRevalidation = (opts && opts.startUninterruptedRevalidation) === true; // Save the current scroll position every time we start a new navigation,
|
|
1473
1460
|
// and track whether we should reset scroll on completion
|
|
1474
1461
|
|
|
1475
1462
|
saveScrollPosition(state.location, state.matches);
|
|
1476
|
-
pendingPreventScrollReset = (opts
|
|
1477
|
-
let loadingNavigation = opts
|
|
1463
|
+
pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;
|
|
1464
|
+
let loadingNavigation = opts && opts.overrideNavigation;
|
|
1478
1465
|
let matches = matchRoutes(dataRoutes, location, init.basename); // Short circuit with a 404 on the root error boundary if we match nothing
|
|
1479
1466
|
|
|
1480
1467
|
if (!matches) {
|
|
@@ -1505,11 +1492,11 @@ function createRouter(init) {
|
|
|
1505
1492
|
|
|
1506
1493
|
|
|
1507
1494
|
pendingNavigationController = new AbortController();
|
|
1508
|
-
let request = createRequest(location, pendingNavigationController.signal, opts
|
|
1495
|
+
let request = createRequest(location, pendingNavigationController.signal, opts && opts.submission);
|
|
1509
1496
|
let pendingActionData;
|
|
1510
1497
|
let pendingError;
|
|
1511
1498
|
|
|
1512
|
-
if (opts
|
|
1499
|
+
if (opts && opts.pendingError) {
|
|
1513
1500
|
// If we have a pendingError, it means the user attempted a GET submission
|
|
1514
1501
|
// with binary FormData so assign here and skip to handleLoaders. That
|
|
1515
1502
|
// way we handle calling loaders above the boundary etc. It's not really
|
|
@@ -1517,7 +1504,7 @@ function createRouter(init) {
|
|
|
1517
1504
|
pendingError = {
|
|
1518
1505
|
[findNearestBoundary(matches).route.id]: opts.pendingError
|
|
1519
1506
|
};
|
|
1520
|
-
} else if (opts
|
|
1507
|
+
} else if (opts && opts.submission) {
|
|
1521
1508
|
// Call action if we received an action submission
|
|
1522
1509
|
let actionOutput = await handleAction(request, location, opts.submission, matches, {
|
|
1523
1510
|
replace: opts.replace
|
|
@@ -1543,7 +1530,7 @@ function createRouter(init) {
|
|
|
1543
1530
|
shortCircuited,
|
|
1544
1531
|
loaderData,
|
|
1545
1532
|
errors
|
|
1546
|
-
} = await handleLoaders(request, location, matches, loadingNavigation, opts
|
|
1533
|
+
} = await handleLoaders(request, location, matches, loadingNavigation, opts && opts.submission, opts && opts.replace, pendingActionData, pendingError);
|
|
1547
1534
|
|
|
1548
1535
|
if (shortCircuited) {
|
|
1549
1536
|
return;
|
|
@@ -1595,7 +1582,7 @@ function createRouter(init) {
|
|
|
1595
1582
|
location: createLocation(state.location, result.location)
|
|
1596
1583
|
}, submission);
|
|
1597
1584
|
|
|
1598
|
-
await startRedirectNavigation(result, redirectNavigation, opts
|
|
1585
|
+
await startRedirectNavigation(result, redirectNavigation, opts && opts.replace);
|
|
1599
1586
|
return {
|
|
1600
1587
|
shortCircuited: true
|
|
1601
1588
|
};
|
|
@@ -1609,7 +1596,7 @@ function createRouter(init) {
|
|
|
1609
1596
|
// back to PUSH so that the user can use the back button to get back to
|
|
1610
1597
|
// the pre-submission form location to try again
|
|
1611
1598
|
|
|
1612
|
-
if ((opts
|
|
1599
|
+
if ((opts && opts.replace) !== true) {
|
|
1613
1600
|
pendingAction = exports.Action.Push;
|
|
1614
1601
|
}
|
|
1615
1602
|
|
|
@@ -1653,7 +1640,7 @@ function createRouter(init) {
|
|
|
1653
1640
|
// about to reload. Note that if this is an action reload we would have
|
|
1654
1641
|
// already cancelled all pending deferreds so this would be a no-op
|
|
1655
1642
|
|
|
1656
|
-
cancelActiveDeferreds(routeId => !(matches
|
|
1643
|
+
cancelActiveDeferreds(routeId => !(matches && matches.some(m => m.route.id === routeId)) || matchesToLoad && matchesToLoad.some(m => m.route.id === routeId)); // Short circuit if we have no loaders to run
|
|
1657
1644
|
|
|
1658
1645
|
if (matchesToLoad.length === 0 && revalidatingFetchers.length === 0) {
|
|
1659
1646
|
completeNavigation(location, {
|
|
@@ -1674,12 +1661,11 @@ function createRouter(init) {
|
|
|
1674
1661
|
|
|
1675
1662
|
if (!isUninterruptedRevalidation) {
|
|
1676
1663
|
revalidatingFetchers.forEach(_ref2 => {
|
|
1677
|
-
var _state$fetchers$get;
|
|
1678
|
-
|
|
1679
1664
|
let [key] = _ref2;
|
|
1665
|
+
const fetcher = state.fetchers.get(key);
|
|
1680
1666
|
let revalidatingFetcher = {
|
|
1681
1667
|
state: "loading",
|
|
1682
|
-
data:
|
|
1668
|
+
data: fetcher && fetcher.data,
|
|
1683
1669
|
formMethod: undefined,
|
|
1684
1670
|
formAction: undefined,
|
|
1685
1671
|
formEncType: undefined,
|
|
@@ -1777,7 +1763,7 @@ function createRouter(init) {
|
|
|
1777
1763
|
let {
|
|
1778
1764
|
path,
|
|
1779
1765
|
submission
|
|
1780
|
-
} = normalizeNavigateOptions(href, opts);
|
|
1766
|
+
} = normalizeNavigateOptions(href, opts, true);
|
|
1781
1767
|
let match = getTargetMatch(matches, path);
|
|
1782
1768
|
|
|
1783
1769
|
if (submission) {
|
|
@@ -1794,8 +1780,6 @@ function createRouter(init) {
|
|
|
1794
1780
|
|
|
1795
1781
|
|
|
1796
1782
|
async function handleFetcherAction(key, routeId, path, match, submission) {
|
|
1797
|
-
var _state$fetchers$get2;
|
|
1798
|
-
|
|
1799
1783
|
interruptActiveLoads();
|
|
1800
1784
|
fetchLoadMatches.delete(key);
|
|
1801
1785
|
|
|
@@ -1808,10 +1792,12 @@ function createRouter(init) {
|
|
|
1808
1792
|
} // Put this fetcher into it's submitting state
|
|
1809
1793
|
|
|
1810
1794
|
|
|
1795
|
+
let existingFetcher = state.fetchers.get(key);
|
|
1796
|
+
|
|
1811
1797
|
let fetcher = _extends({
|
|
1812
1798
|
state: "submitting"
|
|
1813
1799
|
}, submission, {
|
|
1814
|
-
data:
|
|
1800
|
+
data: existingFetcher && existingFetcher.data
|
|
1815
1801
|
});
|
|
1816
1802
|
|
|
1817
1803
|
state.fetchers.set(key, fetcher);
|
|
@@ -1894,12 +1880,11 @@ function createRouter(init) {
|
|
|
1894
1880
|
let [staleKey] = _ref5;
|
|
1895
1881
|
return staleKey !== key;
|
|
1896
1882
|
}).forEach(_ref6 => {
|
|
1897
|
-
var _state$fetchers$get3;
|
|
1898
|
-
|
|
1899
1883
|
let [staleKey] = _ref6;
|
|
1884
|
+
let existingFetcher = state.fetchers.get(staleKey);
|
|
1900
1885
|
let revalidatingFetcher = {
|
|
1901
1886
|
state: "loading",
|
|
1902
|
-
data:
|
|
1887
|
+
data: existingFetcher && existingFetcher.data,
|
|
1903
1888
|
formMethod: undefined,
|
|
1904
1889
|
formAction: undefined,
|
|
1905
1890
|
formEncType: undefined,
|
|
@@ -1954,10 +1939,8 @@ function createRouter(init) {
|
|
|
1954
1939
|
// navigation and complete it with the fetcher data
|
|
1955
1940
|
|
|
1956
1941
|
if (state.navigation.state === "loading" && loadId > pendingNavigationLoadId) {
|
|
1957
|
-
var _pendingNavigationCon3;
|
|
1958
|
-
|
|
1959
1942
|
invariant(pendingAction, "Expected pending action");
|
|
1960
|
-
|
|
1943
|
+
pendingNavigationController && pendingNavigationController.abort();
|
|
1961
1944
|
completeNavigation(state.navigation.location, {
|
|
1962
1945
|
matches,
|
|
1963
1946
|
loaderData,
|
|
@@ -1980,16 +1963,15 @@ function createRouter(init) {
|
|
|
1980
1963
|
|
|
1981
1964
|
|
|
1982
1965
|
async function handleFetcherLoader(key, routeId, path, match) {
|
|
1983
|
-
|
|
1966
|
+
let existingFetcher = state.fetchers.get(key); // Put this fetcher into it's loading state
|
|
1984
1967
|
|
|
1985
|
-
// Put this fetcher into it's loading state
|
|
1986
1968
|
let loadingFetcher = {
|
|
1987
1969
|
state: "loading",
|
|
1988
1970
|
formMethod: undefined,
|
|
1989
1971
|
formAction: undefined,
|
|
1990
1972
|
formEncType: undefined,
|
|
1991
1973
|
formData: undefined,
|
|
1992
|
-
data:
|
|
1974
|
+
data: existingFetcher && existingFetcher.data
|
|
1993
1975
|
};
|
|
1994
1976
|
state.fetchers.set(key, loadingFetcher);
|
|
1995
1977
|
updateState({
|
|
@@ -2588,7 +2570,11 @@ function getStaticContextFromError(routes, context, error) {
|
|
|
2588
2570
|
} // Normalize navigation options by converting formMethod=GET formData objects to
|
|
2589
2571
|
// URLSearchParams so they behave identically to links with query params
|
|
2590
2572
|
|
|
2591
|
-
function normalizeNavigateOptions(to, opts) {
|
|
2573
|
+
function normalizeNavigateOptions(to, opts, isFetcher) {
|
|
2574
|
+
if (isFetcher === void 0) {
|
|
2575
|
+
isFetcher = false;
|
|
2576
|
+
}
|
|
2577
|
+
|
|
2592
2578
|
let path = typeof to === "string" ? to : createPath(to); // Return location verbatim on non-submission navigations
|
|
2593
2579
|
|
|
2594
2580
|
if (!opts || !("formMethod" in opts) && !("formData" in opts)) {
|
|
@@ -2604,7 +2590,7 @@ function normalizeNavigateOptions(to, opts) {
|
|
|
2604
2590
|
submission: {
|
|
2605
2591
|
formMethod: opts.formMethod,
|
|
2606
2592
|
formAction: createHref(parsePath(path)),
|
|
2607
|
-
formEncType:
|
|
2593
|
+
formEncType: opts && opts.formEncType || "application/x-www-form-urlencoded",
|
|
2608
2594
|
formData: opts.formData
|
|
2609
2595
|
}
|
|
2610
2596
|
};
|
|
@@ -2621,7 +2607,14 @@ function normalizeNavigateOptions(to, opts) {
|
|
|
2621
2607
|
let parsedPath = parsePath(path);
|
|
2622
2608
|
|
|
2623
2609
|
try {
|
|
2624
|
-
let searchParams = convertFormDataToSearchParams(opts.formData);
|
|
2610
|
+
let searchParams = convertFormDataToSearchParams(opts.formData); // Since fetcher GET submissions only run a single loader (as opposed to
|
|
2611
|
+
// navigation GET submissions which run all loaders), we need to preserve
|
|
2612
|
+
// any incoming ?index params
|
|
2613
|
+
|
|
2614
|
+
if (isFetcher && parsedPath.search && hasNakedIndexQuery(parsedPath.search)) {
|
|
2615
|
+
searchParams.append("index", "");
|
|
2616
|
+
}
|
|
2617
|
+
|
|
2625
2618
|
parsedPath.search = "?" + searchParams;
|
|
2626
2619
|
} catch (e) {
|
|
2627
2620
|
return {
|
|
@@ -2678,7 +2671,7 @@ function getMatchesToLoad(state, matches, submission, location, isRevalidationRe
|
|
|
2678
2671
|
cancelledDeferredRoutes.some(id => id === match.route.id) || shouldRevalidateLoader(state.location, state.matches[index], submission, location, match, isRevalidationRequired, actionResult))); // Pick fetcher.loads that need to be revalidated
|
|
2679
2672
|
|
|
2680
2673
|
let revalidatingFetchers = [];
|
|
2681
|
-
fetchLoadMatches
|
|
2674
|
+
fetchLoadMatches && fetchLoadMatches.forEach((_ref10, key) => {
|
|
2682
2675
|
let [href, match] = _ref10;
|
|
2683
2676
|
|
|
2684
2677
|
// This fetcher was cancelled from a prior action submission - force reload
|
|
@@ -2707,12 +2700,11 @@ function isNewLoader(currentLoaderData, currentMatch, match) {
|
|
|
2707
2700
|
}
|
|
2708
2701
|
|
|
2709
2702
|
function isNewRouteInstance(currentMatch, match) {
|
|
2710
|
-
|
|
2711
|
-
|
|
2703
|
+
let currentPath = currentMatch.route.path;
|
|
2712
2704
|
return (// param change for this match, /users/123 -> /users/456
|
|
2713
2705
|
currentMatch.pathname !== match.pathname || // splat param changed, which is not present in match.path
|
|
2714
2706
|
// e.g. /files/images/avatar.jpg -> files/finances.xls
|
|
2715
|
-
|
|
2707
|
+
currentPath && currentPath.endsWith("*") && currentMatch.params["*"] !== match.params["*"]
|
|
2716
2708
|
);
|
|
2717
2709
|
}
|
|
2718
2710
|
|
|
@@ -2785,8 +2777,6 @@ async function callLoaderOrAction(type, request, match, skipRedirects, isRouteRe
|
|
|
2785
2777
|
}
|
|
2786
2778
|
|
|
2787
2779
|
if (result instanceof Response) {
|
|
2788
|
-
var _result$headers$get;
|
|
2789
|
-
|
|
2790
2780
|
// Process redirects
|
|
2791
2781
|
let status = result.status;
|
|
2792
2782
|
let location = result.headers.get("Location"); // For SSR single-route requests, we want to hand Responses back directly
|
|
@@ -2813,8 +2803,9 @@ async function callLoaderOrAction(type, request, match, skipRedirects, isRouteRe
|
|
|
2813
2803
|
}
|
|
2814
2804
|
|
|
2815
2805
|
let data;
|
|
2806
|
+
let contentType = result.headers.get("Content-Type");
|
|
2816
2807
|
|
|
2817
|
-
if (
|
|
2808
|
+
if (contentType && contentType.startsWith("application/json")) {
|
|
2818
2809
|
data = await result.json();
|
|
2819
2810
|
} else {
|
|
2820
2811
|
data = await result.text();
|
|
@@ -2926,7 +2917,7 @@ function processRouteLoaderData(matches, matchesToLoad, results, pendingError, a
|
|
|
2926
2917
|
loaderHeaders[id] = result.headers;
|
|
2927
2918
|
}
|
|
2928
2919
|
} else if (isDeferredResult(result)) {
|
|
2929
|
-
activeDeferreds
|
|
2920
|
+
activeDeferreds && activeDeferreds.set(id, result.deferredData);
|
|
2930
2921
|
loaderData[id] = result.deferredData.data; // TODO: Add statusCode/headers once we wire up streaming in Remix
|
|
2931
2922
|
} else {
|
|
2932
2923
|
loaderData[id] = result.data; // Error status codes always override success status codes, but if all
|
|
@@ -2967,11 +2958,9 @@ function processLoaderData(state, matches, matchesToLoad, results, pendingError,
|
|
|
2967
2958
|
let result = fetcherResults[index]; // Process fetcher non-redirect errors
|
|
2968
2959
|
|
|
2969
2960
|
if (isErrorResult(result)) {
|
|
2970
|
-
var _errors;
|
|
2971
|
-
|
|
2972
2961
|
let boundaryMatch = findNearestBoundary(state.matches, match.route.id);
|
|
2973
2962
|
|
|
2974
|
-
if (!(
|
|
2963
|
+
if (!(errors && errors[boundaryMatch.route.id])) {
|
|
2975
2964
|
errors = _extends({}, errors, {
|
|
2976
2965
|
[boundaryMatch.route.id]: result.error
|
|
2977
2966
|
});
|
|
@@ -3081,7 +3070,7 @@ function isErrorResult(result) {
|
|
|
3081
3070
|
}
|
|
3082
3071
|
|
|
3083
3072
|
function isRedirectResult(result) {
|
|
3084
|
-
return (result
|
|
3073
|
+
return (result && result.type) === ResultType.redirect;
|
|
3085
3074
|
}
|
|
3086
3075
|
|
|
3087
3076
|
async function resolveDeferredResults(currentMatches, matchesToLoad, results, signal, isFetcher, currentLoaderData) {
|
|
@@ -3089,7 +3078,7 @@ async function resolveDeferredResults(currentMatches, matchesToLoad, results, si
|
|
|
3089
3078
|
let result = results[index];
|
|
3090
3079
|
let match = matchesToLoad[index];
|
|
3091
3080
|
let currentMatch = currentMatches.find(m => m.route.id === match.route.id);
|
|
3092
|
-
let isRevalidatingLoader = currentMatch != null && !isNewRouteInstance(currentMatch, match) && (currentLoaderData
|
|
3081
|
+
let isRevalidatingLoader = currentMatch != null && !isNewRouteInstance(currentMatch, match) && (currentLoaderData && currentLoaderData[match.route.id]) !== undefined;
|
|
3093
3082
|
|
|
3094
3083
|
if (isDeferredResult(result) && (isFetcher || isRevalidatingLoader)) {
|
|
3095
3084
|
// Note: we do not have to touch activeDeferreds here since we race them
|