@remix-run/router 0.0.0-experimental-a077dc2d → 0.0.0-experimental-e192105b
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 +22 -0
- package/dist/router.cjs.js +135 -65
- package/dist/router.cjs.js.map +1 -1
- package/dist/router.d.ts +3 -0
- package/dist/router.js +131 -65
- package/dist/router.js.map +1 -1
- package/dist/router.umd.js +135 -65
- 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/package.json +1 -1
- package/router.ts +184 -93
package/dist/router.d.ts
CHANGED
|
@@ -304,7 +304,9 @@ type ViewTransitionOpts = {
|
|
|
304
304
|
*/
|
|
305
305
|
export interface RouterSubscriber {
|
|
306
306
|
(state: RouterState, opts: {
|
|
307
|
+
deletedFetchers: string[];
|
|
307
308
|
unstable_viewTransitionOpts?: ViewTransitionOpts;
|
|
309
|
+
unstable_flushSync?: boolean;
|
|
308
310
|
}): void;
|
|
309
311
|
}
|
|
310
312
|
/**
|
|
@@ -324,6 +326,7 @@ export type RelativeRoutingType = "route" | "path";
|
|
|
324
326
|
type BaseNavigateOrFetchOptions = {
|
|
325
327
|
preventScrollReset?: boolean;
|
|
326
328
|
relative?: RelativeRoutingType;
|
|
329
|
+
unstable_flushSync?: boolean;
|
|
327
330
|
};
|
|
328
331
|
type BaseNavigateOptions = BaseNavigateOrFetchOptions & {
|
|
329
332
|
replace?: boolean;
|
package/dist/router.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @remix-run/router v0.0.0-experimental-
|
|
2
|
+
* @remix-run/router v0.0.0-experimental-e192105b
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -1386,6 +1386,8 @@ function createRouter(init) {
|
|
|
1386
1386
|
let pendingNavigationController;
|
|
1387
1387
|
// Should the current navigation enable document.startViewTransition?
|
|
1388
1388
|
let pendingViewTransitionEnabled = false;
|
|
1389
|
+
// Should the current navigation use flushSync for state updates?
|
|
1390
|
+
let pendingFlushSync = false;
|
|
1389
1391
|
// Store applied view transitions so we can apply them on POP
|
|
1390
1392
|
let appliedViewTransitions = new Map();
|
|
1391
1393
|
// Cleanup function for persisting applied transitions to sessionStorage
|
|
@@ -1418,6 +1420,8 @@ function createRouter(init) {
|
|
|
1418
1420
|
let fetchRedirectIds = new Set();
|
|
1419
1421
|
// Most recent href/match for fetcher.load calls for fetchers
|
|
1420
1422
|
let fetchLoadMatches = new Map();
|
|
1423
|
+
// Ref-count mounted fetchers so we know when it's ok to clean them up
|
|
1424
|
+
let activeFetchers = new Map();
|
|
1421
1425
|
// Fetchers that have requested a delete when using v7_fetcherPersist,
|
|
1422
1426
|
// they'll be officially removed after they return to idle
|
|
1423
1427
|
let deletedFetchers = new Set();
|
|
@@ -1479,6 +1483,8 @@ function createRouter(init) {
|
|
|
1479
1483
|
blockers.set(blockerKey, IDLE_BLOCKER);
|
|
1480
1484
|
updateState({
|
|
1481
1485
|
blockers
|
|
1486
|
+
}, {
|
|
1487
|
+
flushSync: false
|
|
1482
1488
|
});
|
|
1483
1489
|
}
|
|
1484
1490
|
});
|
|
@@ -1523,28 +1529,39 @@ function createRouter(init) {
|
|
|
1523
1529
|
return () => subscribers.delete(fn);
|
|
1524
1530
|
}
|
|
1525
1531
|
// Update our state and notify the calling context of the change
|
|
1526
|
-
function updateState(newState,
|
|
1532
|
+
function updateState(newState, opts) {
|
|
1527
1533
|
state = _extends({}, state, newState);
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1534
|
+
// Prep fetcher cleanup so we can tell the UI which fetcher data entries
|
|
1535
|
+
// can be removed
|
|
1536
|
+
let completedFetchers = [];
|
|
1537
|
+
let deletedFetchersKeys = [];
|
|
1532
1538
|
if (future.v7_fetcherPersist) {
|
|
1533
1539
|
state.fetchers.forEach((fetcher, key) => {
|
|
1534
1540
|
if (fetcher.state === "idle") {
|
|
1535
1541
|
if (deletedFetchers.has(key)) {
|
|
1536
|
-
//
|
|
1537
|
-
|
|
1538
|
-
deleteFetcher(key);
|
|
1542
|
+
// Unmounted from the UI and can be totally removed
|
|
1543
|
+
deletedFetchersKeys.push(key);
|
|
1539
1544
|
} else {
|
|
1540
|
-
//
|
|
1541
|
-
//
|
|
1542
|
-
|
|
1543
|
-
state.fetchers.delete(key);
|
|
1545
|
+
// Returned to idle but still mounted in the UI, so semi-remains for
|
|
1546
|
+
// revalidations and such
|
|
1547
|
+
completedFetchers.push(key);
|
|
1544
1548
|
}
|
|
1545
1549
|
}
|
|
1546
1550
|
});
|
|
1547
1551
|
}
|
|
1552
|
+
// Iterate over a local copy so that if flushSync is used and we end up
|
|
1553
|
+
// removing and adding a new subscriber due to the useCallback dependencies,
|
|
1554
|
+
// we don't get ourselves into a loop calling the new subscriber immediately
|
|
1555
|
+
[...subscribers].forEach(subscriber => subscriber(state, {
|
|
1556
|
+
deletedFetchers: deletedFetchersKeys,
|
|
1557
|
+
unstable_viewTransitionOpts: opts.viewTransitionOpts,
|
|
1558
|
+
unstable_flushSync: opts.flushSync
|
|
1559
|
+
}));
|
|
1560
|
+
// Remove idle fetchers from state since we only care about in-flight fetchers.
|
|
1561
|
+
if (future.v7_fetcherPersist) {
|
|
1562
|
+
completedFetchers.forEach(key => state.fetchers.delete(key));
|
|
1563
|
+
deletedFetchersKeys.forEach(key => deleteFetcher(key));
|
|
1564
|
+
}
|
|
1548
1565
|
}
|
|
1549
1566
|
// Complete a navigation returning the state.navigation back to the IDLE_NAVIGATION
|
|
1550
1567
|
// and setting state.[historyAction/location/matches] to the new route.
|
|
@@ -1638,11 +1655,15 @@ function createRouter(init) {
|
|
|
1638
1655
|
restoreScrollPosition: getSavedScrollPosition(location, newState.matches || state.matches),
|
|
1639
1656
|
preventScrollReset,
|
|
1640
1657
|
blockers
|
|
1641
|
-
}),
|
|
1658
|
+
}), {
|
|
1659
|
+
viewTransitionOpts,
|
|
1660
|
+
flushSync: pendingFlushSync
|
|
1661
|
+
});
|
|
1642
1662
|
// Reset stateful navigation vars
|
|
1643
1663
|
pendingAction = Action.Pop;
|
|
1644
1664
|
pendingPreventScrollReset = false;
|
|
1645
1665
|
pendingViewTransitionEnabled = false;
|
|
1666
|
+
pendingFlushSync = false;
|
|
1646
1667
|
isUninterruptedRevalidation = false;
|
|
1647
1668
|
isRevalidationRequired = false;
|
|
1648
1669
|
cancelledDeferredRoutes = [];
|
|
@@ -1681,6 +1702,7 @@ function createRouter(init) {
|
|
|
1681
1702
|
historyAction = Action.Replace;
|
|
1682
1703
|
}
|
|
1683
1704
|
let preventScrollReset = opts && "preventScrollReset" in opts ? opts.preventScrollReset === true : undefined;
|
|
1705
|
+
let flushSync = (opts && opts.unstable_flushSync) === true;
|
|
1684
1706
|
let blockerKey = shouldBlockNavigation({
|
|
1685
1707
|
currentLocation,
|
|
1686
1708
|
nextLocation,
|
|
@@ -1706,6 +1728,8 @@ function createRouter(init) {
|
|
|
1706
1728
|
blockers.set(blockerKey, IDLE_BLOCKER);
|
|
1707
1729
|
updateState({
|
|
1708
1730
|
blockers
|
|
1731
|
+
}, {
|
|
1732
|
+
flushSync
|
|
1709
1733
|
});
|
|
1710
1734
|
}
|
|
1711
1735
|
});
|
|
@@ -1718,7 +1742,8 @@ function createRouter(init) {
|
|
|
1718
1742
|
pendingError: error,
|
|
1719
1743
|
preventScrollReset,
|
|
1720
1744
|
replace: opts && opts.replace,
|
|
1721
|
-
enableViewTransition: opts && opts.unstable_viewTransition
|
|
1745
|
+
enableViewTransition: opts && opts.unstable_viewTransition,
|
|
1746
|
+
flushSync
|
|
1722
1747
|
});
|
|
1723
1748
|
}
|
|
1724
1749
|
// Revalidate all current loaders. If a navigation is in progress or if this
|
|
@@ -1728,6 +1753,8 @@ function createRouter(init) {
|
|
|
1728
1753
|
interruptActiveLoads();
|
|
1729
1754
|
updateState({
|
|
1730
1755
|
revalidation: "loading"
|
|
1756
|
+
}, {
|
|
1757
|
+
flushSync: false
|
|
1731
1758
|
});
|
|
1732
1759
|
// If we're currently submitting an action, we don't need to start a new
|
|
1733
1760
|
// navigation, we'll just let the follow up loader execution call all loaders
|
|
@@ -1766,6 +1793,7 @@ function createRouter(init) {
|
|
|
1766
1793
|
saveScrollPosition(state.location, state.matches);
|
|
1767
1794
|
pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;
|
|
1768
1795
|
pendingViewTransitionEnabled = (opts && opts.enableViewTransition) === true;
|
|
1796
|
+
pendingFlushSync = (opts && opts.flushSync) === true;
|
|
1769
1797
|
let routesToUse = inFlightDataRoutes || dataRoutes;
|
|
1770
1798
|
let loadingNavigation = opts && opts.overrideNavigation;
|
|
1771
1799
|
let matches = matchRoutes(routesToUse, location, basename);
|
|
@@ -1863,6 +1891,8 @@ function createRouter(init) {
|
|
|
1863
1891
|
let navigation = getSubmittingNavigation(location, submission);
|
|
1864
1892
|
updateState({
|
|
1865
1893
|
navigation
|
|
1894
|
+
}, {
|
|
1895
|
+
flushSync: pendingFlushSync
|
|
1866
1896
|
});
|
|
1867
1897
|
// Call our action and get the result
|
|
1868
1898
|
let result;
|
|
@@ -1983,7 +2013,9 @@ function createRouter(init) {
|
|
|
1983
2013
|
actionData
|
|
1984
2014
|
} : {}, revalidatingFetchers.length > 0 ? {
|
|
1985
2015
|
fetchers: new Map(state.fetchers)
|
|
1986
|
-
} : {})
|
|
2016
|
+
} : {}), {
|
|
2017
|
+
flushSync: pendingFlushSync
|
|
2018
|
+
});
|
|
1987
2019
|
}
|
|
1988
2020
|
revalidatingFetchers.forEach(rf => {
|
|
1989
2021
|
if (fetchControllers.has(rf.key)) {
|
|
@@ -2061,22 +2093,22 @@ function createRouter(init) {
|
|
|
2061
2093
|
fetchers: new Map(state.fetchers)
|
|
2062
2094
|
} : {});
|
|
2063
2095
|
}
|
|
2064
|
-
function getFetcher(key) {
|
|
2065
|
-
return state.fetchers.get(key) || IDLE_FETCHER;
|
|
2066
|
-
}
|
|
2067
2096
|
// Trigger a fetcher load/submit for the given fetcher key
|
|
2068
2097
|
function fetch(key, routeId, href, opts) {
|
|
2069
2098
|
if (isServer) {
|
|
2070
2099
|
throw new Error("router.fetch() was called during the server render, but it shouldn't be. " + "You are likely calling a useFetcher() method in the body of your component. " + "Try moving it to a useEffect or a callback.");
|
|
2071
2100
|
}
|
|
2072
2101
|
if (fetchControllers.has(key)) abortFetcher(key);
|
|
2102
|
+
let flushSync = (opts && opts.unstable_flushSync) === true;
|
|
2073
2103
|
let routesToUse = inFlightDataRoutes || dataRoutes;
|
|
2074
2104
|
let normalizedPath = normalizeTo(state.location, state.matches, basename, future.v7_prependBasename, href, routeId, opts == null ? void 0 : opts.relative);
|
|
2075
2105
|
let matches = matchRoutes(routesToUse, normalizedPath, basename);
|
|
2076
2106
|
if (!matches) {
|
|
2077
2107
|
setFetcherError(key, routeId, getInternalRouterError(404, {
|
|
2078
2108
|
pathname: normalizedPath
|
|
2079
|
-
})
|
|
2109
|
+
}), {
|
|
2110
|
+
flushSync
|
|
2111
|
+
});
|
|
2080
2112
|
return;
|
|
2081
2113
|
}
|
|
2082
2114
|
let {
|
|
@@ -2085,13 +2117,15 @@ function createRouter(init) {
|
|
|
2085
2117
|
error
|
|
2086
2118
|
} = normalizeNavigateOptions(future.v7_normalizeFormMethod, true, normalizedPath, opts);
|
|
2087
2119
|
if (error) {
|
|
2088
|
-
setFetcherError(key, routeId, error
|
|
2120
|
+
setFetcherError(key, routeId, error, {
|
|
2121
|
+
flushSync
|
|
2122
|
+
});
|
|
2089
2123
|
return;
|
|
2090
2124
|
}
|
|
2091
2125
|
let match = getTargetMatch(matches, path);
|
|
2092
2126
|
pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;
|
|
2093
2127
|
if (submission && isMutationMethod(submission.formMethod)) {
|
|
2094
|
-
handleFetcherAction(key, routeId, path, match, matches, submission);
|
|
2128
|
+
handleFetcherAction(key, routeId, path, match, matches, flushSync, submission);
|
|
2095
2129
|
return;
|
|
2096
2130
|
}
|
|
2097
2131
|
// Store off the match so we can call it's shouldRevalidate on subsequent
|
|
@@ -2100,11 +2134,11 @@ function createRouter(init) {
|
|
|
2100
2134
|
routeId,
|
|
2101
2135
|
path
|
|
2102
2136
|
});
|
|
2103
|
-
handleFetcherLoader(key, routeId, path, match, matches, submission);
|
|
2137
|
+
handleFetcherLoader(key, routeId, path, match, matches, flushSync, submission);
|
|
2104
2138
|
}
|
|
2105
2139
|
// Call the action for the matched fetcher.submit(), and then handle redirects,
|
|
2106
2140
|
// errors, and revalidation
|
|
2107
|
-
async function handleFetcherAction(key, routeId, path, match, requestMatches, submission) {
|
|
2141
|
+
async function handleFetcherAction(key, routeId, path, match, requestMatches, flushSync, submission) {
|
|
2108
2142
|
interruptActiveLoads();
|
|
2109
2143
|
fetchLoadMatches.delete(key);
|
|
2110
2144
|
if (!match.route.action && !match.route.lazy) {
|
|
@@ -2113,15 +2147,15 @@ function createRouter(init) {
|
|
|
2113
2147
|
pathname: path,
|
|
2114
2148
|
routeId: routeId
|
|
2115
2149
|
});
|
|
2116
|
-
setFetcherError(key, routeId, error
|
|
2150
|
+
setFetcherError(key, routeId, error, {
|
|
2151
|
+
flushSync
|
|
2152
|
+
});
|
|
2117
2153
|
return;
|
|
2118
2154
|
}
|
|
2119
2155
|
// Put this fetcher into it's submitting state
|
|
2120
2156
|
let existingFetcher = state.fetchers.get(key);
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
updateState({
|
|
2124
|
-
fetchers: new Map(state.fetchers)
|
|
2157
|
+
updateFetcherState(key, getSubmittingFetcher(submission, existingFetcher), {
|
|
2158
|
+
flushSync
|
|
2125
2159
|
});
|
|
2126
2160
|
// Call the action for the fetcher
|
|
2127
2161
|
let abortController = new AbortController();
|
|
@@ -2130,13 +2164,19 @@ function createRouter(init) {
|
|
|
2130
2164
|
let originatingLoadId = incrementingLoadId;
|
|
2131
2165
|
let actionResult = await callLoaderOrAction("action", fetchRequest, match, requestMatches, manifest, mapRouteProperties, basename);
|
|
2132
2166
|
if (fetchRequest.signal.aborted) {
|
|
2133
|
-
// We can delete this so long as we weren't aborted by
|
|
2167
|
+
// We can delete this so long as we weren't aborted by our own fetcher
|
|
2134
2168
|
// re-submit which would have put _new_ controller is in fetchControllers
|
|
2135
2169
|
if (fetchControllers.get(key) === abortController) {
|
|
2136
2170
|
fetchControllers.delete(key);
|
|
2137
2171
|
}
|
|
2138
2172
|
return;
|
|
2139
2173
|
}
|
|
2174
|
+
if (deletedFetchers.has(key)) {
|
|
2175
|
+
updateFetcherState(key, getDoneFetcher(undefined), {
|
|
2176
|
+
flushSync
|
|
2177
|
+
});
|
|
2178
|
+
return;
|
|
2179
|
+
}
|
|
2140
2180
|
if (isRedirectResult(actionResult)) {
|
|
2141
2181
|
fetchControllers.delete(key);
|
|
2142
2182
|
if (pendingNavigationLoadId > originatingLoadId) {
|
|
@@ -2144,18 +2184,14 @@ function createRouter(init) {
|
|
|
2144
2184
|
// should take precedence over this redirect navigation. We already
|
|
2145
2185
|
// set isRevalidationRequired so all loaders for the new route should
|
|
2146
2186
|
// fire unless opted out via shouldRevalidate
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
updateState({
|
|
2150
|
-
fetchers: new Map(state.fetchers)
|
|
2187
|
+
updateFetcherState(key, getDoneFetcher(undefined), {
|
|
2188
|
+
flushSync
|
|
2151
2189
|
});
|
|
2152
2190
|
return;
|
|
2153
2191
|
} else {
|
|
2154
2192
|
fetchRedirectIds.add(key);
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
updateState({
|
|
2158
|
-
fetchers: new Map(state.fetchers)
|
|
2193
|
+
updateFetcherState(key, getLoadingFetcher(submission), {
|
|
2194
|
+
flushSync
|
|
2159
2195
|
});
|
|
2160
2196
|
return startRedirectNavigation(state, actionResult, {
|
|
2161
2197
|
fetcherSubmission: submission
|
|
@@ -2164,7 +2200,9 @@ function createRouter(init) {
|
|
|
2164
2200
|
}
|
|
2165
2201
|
// Process any non-redirect errors thrown
|
|
2166
2202
|
if (isErrorResult(actionResult)) {
|
|
2167
|
-
setFetcherError(key, routeId, actionResult.error
|
|
2203
|
+
setFetcherError(key, routeId, actionResult.error, {
|
|
2204
|
+
flushSync
|
|
2205
|
+
});
|
|
2168
2206
|
return;
|
|
2169
2207
|
}
|
|
2170
2208
|
if (isDeferredResult(actionResult)) {
|
|
@@ -2204,6 +2242,8 @@ function createRouter(init) {
|
|
|
2204
2242
|
});
|
|
2205
2243
|
updateState({
|
|
2206
2244
|
fetchers: new Map(state.fetchers)
|
|
2245
|
+
}, {
|
|
2246
|
+
flushSync
|
|
2207
2247
|
});
|
|
2208
2248
|
let abortPendingFetchRevalidations = () => revalidatingFetchers.forEach(rf => abortFetcher(rf.key));
|
|
2209
2249
|
abortController.signal.addEventListener("abort", abortPendingFetchRevalidations);
|
|
@@ -2262,18 +2302,17 @@ function createRouter(init) {
|
|
|
2262
2302
|
errors,
|
|
2263
2303
|
loaderData: mergeLoaderData(state.loaderData, loaderData, matches, errors),
|
|
2264
2304
|
fetchers: new Map(state.fetchers)
|
|
2305
|
+
}, {
|
|
2306
|
+
flushSync
|
|
2265
2307
|
});
|
|
2266
2308
|
isRevalidationRequired = false;
|
|
2267
2309
|
}
|
|
2268
2310
|
}
|
|
2269
2311
|
// Call the matched loader for fetcher.load(), handling redirects, errors, etc.
|
|
2270
|
-
async function handleFetcherLoader(key, routeId, path, match, matches, submission) {
|
|
2312
|
+
async function handleFetcherLoader(key, routeId, path, match, matches, flushSync, submission) {
|
|
2271
2313
|
let existingFetcher = state.fetchers.get(key);
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
state.fetchers.set(key, loadingFetcher);
|
|
2275
|
-
updateState({
|
|
2276
|
-
fetchers: new Map(state.fetchers)
|
|
2314
|
+
updateFetcherState(key, getLoadingFetcher(submission, existingFetcher ? existingFetcher.data : undefined), {
|
|
2315
|
+
flushSync
|
|
2277
2316
|
});
|
|
2278
2317
|
// Call the loader for this fetcher route match
|
|
2279
2318
|
let abortController = new AbortController();
|
|
@@ -2296,15 +2335,19 @@ function createRouter(init) {
|
|
|
2296
2335
|
if (fetchRequest.signal.aborted) {
|
|
2297
2336
|
return;
|
|
2298
2337
|
}
|
|
2338
|
+
if (deletedFetchers.has(key)) {
|
|
2339
|
+
updateFetcherState(key, getDoneFetcher(undefined), {
|
|
2340
|
+
flushSync
|
|
2341
|
+
});
|
|
2342
|
+
return;
|
|
2343
|
+
}
|
|
2299
2344
|
// If the loader threw a redirect Response, start a new REPLACE navigation
|
|
2300
2345
|
if (isRedirectResult(result)) {
|
|
2301
2346
|
if (pendingNavigationLoadId > originatingLoadId) {
|
|
2302
2347
|
// A new navigation was kicked off after our loader started, so that
|
|
2303
2348
|
// should take precedence over this redirect navigation
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
updateState({
|
|
2307
|
-
fetchers: new Map(state.fetchers)
|
|
2349
|
+
updateFetcherState(key, getDoneFetcher(undefined), {
|
|
2350
|
+
flushSync
|
|
2308
2351
|
});
|
|
2309
2352
|
return;
|
|
2310
2353
|
} else {
|
|
@@ -2315,25 +2358,15 @@ function createRouter(init) {
|
|
|
2315
2358
|
}
|
|
2316
2359
|
// Process any non-redirect errors thrown
|
|
2317
2360
|
if (isErrorResult(result)) {
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
// TODO: In remix, this would reset to IDLE_NAVIGATION if it was a catch -
|
|
2321
|
-
// do we need to behave any differently with our non-redirect errors?
|
|
2322
|
-
// What if it was a non-redirect Response?
|
|
2323
|
-
updateState({
|
|
2324
|
-
fetchers: new Map(state.fetchers),
|
|
2325
|
-
errors: {
|
|
2326
|
-
[boundaryMatch.route.id]: result.error
|
|
2327
|
-
}
|
|
2361
|
+
setFetcherError(key, routeId, result.error, {
|
|
2362
|
+
flushSync
|
|
2328
2363
|
});
|
|
2329
2364
|
return;
|
|
2330
2365
|
}
|
|
2331
2366
|
invariant(!isDeferredResult(result), "Unhandled fetcher deferred data");
|
|
2332
2367
|
// Put the fetcher back into an idle state
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
updateState({
|
|
2336
|
-
fetchers: new Map(state.fetchers)
|
|
2368
|
+
updateFetcherState(key, getDoneFetcher(result.data), {
|
|
2369
|
+
flushSync
|
|
2337
2370
|
});
|
|
2338
2371
|
}
|
|
2339
2372
|
/**
|
|
@@ -2469,7 +2502,15 @@ function createRouter(init) {
|
|
|
2469
2502
|
}
|
|
2470
2503
|
});
|
|
2471
2504
|
}
|
|
2472
|
-
function
|
|
2505
|
+
function updateFetcherState(key, fetcher, opts) {
|
|
2506
|
+
state.fetchers.set(key, fetcher);
|
|
2507
|
+
updateState({
|
|
2508
|
+
fetchers: new Map(state.fetchers)
|
|
2509
|
+
}, {
|
|
2510
|
+
flushSync: opts.flushSync
|
|
2511
|
+
});
|
|
2512
|
+
}
|
|
2513
|
+
function setFetcherError(key, routeId, error, opts) {
|
|
2473
2514
|
let boundaryMatch = findNearestBoundary(state.matches, routeId);
|
|
2474
2515
|
deleteFetcher(key);
|
|
2475
2516
|
updateState({
|
|
@@ -2477,8 +2518,21 @@ function createRouter(init) {
|
|
|
2477
2518
|
[boundaryMatch.route.id]: error
|
|
2478
2519
|
},
|
|
2479
2520
|
fetchers: new Map(state.fetchers)
|
|
2521
|
+
}, {
|
|
2522
|
+
flushSync: opts.flushSync
|
|
2480
2523
|
});
|
|
2481
2524
|
}
|
|
2525
|
+
function getFetcher(key) {
|
|
2526
|
+
if (future.v7_fetcherPersist) {
|
|
2527
|
+
activeFetchers.set(key, (activeFetchers.get(key) || 0) + 1);
|
|
2528
|
+
// If this fetcher was previously marked for deletion, unmark it since we
|
|
2529
|
+
// have a new instance
|
|
2530
|
+
if (deletedFetchers.has(key)) {
|
|
2531
|
+
deletedFetchers.delete(key);
|
|
2532
|
+
}
|
|
2533
|
+
}
|
|
2534
|
+
return state.fetchers.get(key) || IDLE_FETCHER;
|
|
2535
|
+
}
|
|
2482
2536
|
function deleteFetcher(key) {
|
|
2483
2537
|
let fetcher = state.fetchers.get(key);
|
|
2484
2538
|
// Don't abort the controller if this is a deletion of a fetcher.submit()
|
|
@@ -2495,12 +2549,20 @@ function createRouter(init) {
|
|
|
2495
2549
|
}
|
|
2496
2550
|
function deleteFetcherAndUpdateState(key) {
|
|
2497
2551
|
if (future.v7_fetcherPersist) {
|
|
2498
|
-
|
|
2552
|
+
let count = (activeFetchers.get(key) || 0) - 1;
|
|
2553
|
+
if (count <= 0) {
|
|
2554
|
+
activeFetchers.delete(key);
|
|
2555
|
+
deletedFetchers.add(key);
|
|
2556
|
+
} else {
|
|
2557
|
+
activeFetchers.set(key, count);
|
|
2558
|
+
}
|
|
2499
2559
|
} else {
|
|
2500
2560
|
deleteFetcher(key);
|
|
2501
2561
|
}
|
|
2502
2562
|
updateState({
|
|
2503
2563
|
fetchers: new Map(state.fetchers)
|
|
2564
|
+
}, {
|
|
2565
|
+
flushSync: false
|
|
2504
2566
|
});
|
|
2505
2567
|
}
|
|
2506
2568
|
function abortFetcher(key) {
|
|
@@ -2568,6 +2630,8 @@ function createRouter(init) {
|
|
|
2568
2630
|
blockers.set(key, newBlocker);
|
|
2569
2631
|
updateState({
|
|
2570
2632
|
blockers
|
|
2633
|
+
}, {
|
|
2634
|
+
flushSync: false
|
|
2571
2635
|
});
|
|
2572
2636
|
}
|
|
2573
2637
|
function shouldBlockNavigation(_ref2) {
|
|
@@ -2631,6 +2695,8 @@ function createRouter(init) {
|
|
|
2631
2695
|
if (y != null) {
|
|
2632
2696
|
updateState({
|
|
2633
2697
|
restoreScrollPosition: y
|
|
2698
|
+
}, {
|
|
2699
|
+
flushSync: false
|
|
2634
2700
|
});
|
|
2635
2701
|
}
|
|
2636
2702
|
}
|