@remix-run/router 0.0.0-experimental-9ffbba722 → 0.0.0-experimental-b3c9fc11b
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 +34 -0
- package/dist/index.d.ts +1 -1
- package/dist/router.cjs.js +29 -50
- package/dist/router.cjs.js.map +1 -1
- package/dist/router.js +27 -49
- package/dist/router.js.map +1 -1
- package/dist/router.umd.js +29 -50
- 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/index.ts +1 -0
- package/package.json +1 -1
- package/router.ts +34 -52
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,39 @@
|
|
|
1
1
|
# `@remix-run/router`
|
|
2
2
|
|
|
3
|
+
## 1.19.0-pre.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [REMOVE] Export DataWithResponseInit for Remix usage ([#11859](https://github.com/remix-run/react-router/pull/11859))
|
|
8
|
+
|
|
9
|
+
## 1.19.0-pre.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- Add a new `unstable_data()` API for usage with Remix Single Fetch ([#11836](https://github.com/remix-run/react-router/pull/11836))
|
|
14
|
+
|
|
15
|
+
- This API is not intended for direct usage in React Router SPA applications
|
|
16
|
+
- It is primarily intended for usage with `createStaticHandler.query()` to allow loaders/actions to return arbitrary data + `status`/`headers` without forcing the serialization of data into a `Response` instance
|
|
17
|
+
- This allows for more advanced serialization tactics via `unstable_dataStrategy` such as serializing via `turbo-stream` in Remix Single Fetch
|
|
18
|
+
- ⚠️ This removes the `status` field from `HandlerResult`
|
|
19
|
+
- If you need to return a specific `status` from `unstable_dataStrategy` you should instead do so via `unstable_data()`
|
|
20
|
+
|
|
21
|
+
- Add a new `replace(url, init?)` alternative to `redirect(url, init?)` that performs a `history.replaceState` instead of a `history.pushState` on client-side navigation redirects ([#11811](https://github.com/remix-run/react-router/pull/11811))
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- Fix internal cleanup of interrupted fetchers to avoid invalid revalidations on navigations ([#11839](https://github.com/remix-run/react-router/pull/11839))
|
|
26
|
+
|
|
27
|
+
- When a `fetcher.load` is interrupted by an `action` submission, we track it internally and force revalidation once the `action` completes
|
|
28
|
+
- We previously only cleared out this internal tracking info on a successful _navigation_ submission
|
|
29
|
+
- Therefore, if the `fetcher.load` was interrupted by a `fetcher.submit`, then we wouldn't remove it from this internal tracking info on successful load (incorrectly)
|
|
30
|
+
- And then on the next navigation it's presence in the internal tracking would automatically trigger execution of the `fetcher.load` again, ignoring any `shouldRevalidate` logic
|
|
31
|
+
- This fix cleans up the internal tracking so it applies to both navigation submission and fetcher submissions
|
|
32
|
+
|
|
33
|
+
- Fix initial hydration behavior when using `future.v7_partialHydration` along with `unstable_patchRoutesOnMiss` ([#11838](https://github.com/remix-run/react-router/pull/11838))
|
|
34
|
+
|
|
35
|
+
- During initial hydration, `router.state.matches` will now include any partial matches so that we can render ancestor `HydrateFallback` components
|
|
36
|
+
|
|
3
37
|
## 1.18.0
|
|
4
38
|
|
|
5
39
|
### Minor Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { ActionFunction, ActionFunctionArgs, AgnosticDataIndexRouteObject, AgnosticDataNonIndexRouteObject, AgnosticDataRouteMatch, AgnosticDataRouteObject, AgnosticIndexRouteObject, AgnosticNonIndexRouteObject, AgnosticRouteMatch, AgnosticRouteObject, DataStrategyFunction as unstable_DataStrategyFunction, DataStrategyFunctionArgs as unstable_DataStrategyFunctionArgs, DataStrategyMatch as unstable_DataStrategyMatch, ErrorResponse, FormEncType, FormMethod, HandlerResult as unstable_HandlerResult, HTMLFormMethod, JsonFunction, LazyRouteFunction, LoaderFunction, LoaderFunctionArgs, ParamParseKey, Params, AgnosticPatchRoutesOnMissFunction as unstable_AgnosticPatchRoutesOnMissFunction, PathMatch, PathParam, PathPattern, RedirectFunction, ShouldRevalidateFunction, ShouldRevalidateFunctionArgs, TrackedPromise, UIMatch, V7_FormMethod, } from "./utils";
|
|
1
|
+
export type { ActionFunction, ActionFunctionArgs, AgnosticDataIndexRouteObject, AgnosticDataNonIndexRouteObject, AgnosticDataRouteMatch, AgnosticDataRouteObject, AgnosticIndexRouteObject, AgnosticNonIndexRouteObject, AgnosticRouteMatch, AgnosticRouteObject, DataStrategyFunction as unstable_DataStrategyFunction, DataStrategyFunctionArgs as unstable_DataStrategyFunctionArgs, DataStrategyMatch as unstable_DataStrategyMatch, ErrorResponse, FormEncType, FormMethod, HandlerResult as unstable_HandlerResult, HTMLFormMethod, JsonFunction, LazyRouteFunction, LoaderFunction, LoaderFunctionArgs, ParamParseKey, Params, AgnosticPatchRoutesOnMissFunction as unstable_AgnosticPatchRoutesOnMissFunction, PathMatch, PathParam, PathPattern, RedirectFunction, ShouldRevalidateFunction, ShouldRevalidateFunctionArgs, TrackedPromise, UIMatch, V7_FormMethod, DataWithResponseInit as UNSAFE_DataWithResponseInit, } from "./utils";
|
|
2
2
|
export { AbortedDeferredError, data as unstable_data, defer, generatePath, getToPathname, isRouteErrorResponse, joinPaths, json, matchPath, matchRoutes, normalizePathname, redirect, redirectDocument, replace, resolvePath, resolveTo, stripBasename, } from "./utils";
|
|
3
3
|
export type { BrowserHistory, BrowserHistoryOptions, HashHistory, HashHistoryOptions, History, InitialEntry, Location, MemoryHistory, MemoryHistoryOptions, Path, To, } from "./history";
|
|
4
4
|
export { Action, createBrowserHistory, createHashHistory, createMemoryHistory, createPath, parsePath, } from "./history";
|
package/dist/router.cjs.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @remix-run/router v0.0.0-experimental-
|
|
2
|
+
* @remix-run/router v0.0.0-experimental-b3c9fc11b
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -1765,7 +1765,7 @@ function createRouter(init) {
|
|
|
1765
1765
|
// In SSR apps (with `hydrationData`), we expect that the server will send
|
|
1766
1766
|
// up the proper matched routes so we don't want to run lazy discovery on
|
|
1767
1767
|
// initial hydration and want to hydrate into the splat route.
|
|
1768
|
-
if (initialMatches &&
|
|
1768
|
+
if (initialMatches && !init.hydrationData) {
|
|
1769
1769
|
let fogOfWar = checkFogOfWar(initialMatches, dataRoutes, init.history.location.pathname);
|
|
1770
1770
|
if (fogOfWar.active) {
|
|
1771
1771
|
initialMatches = null;
|
|
@@ -1773,9 +1773,18 @@ function createRouter(init) {
|
|
|
1773
1773
|
}
|
|
1774
1774
|
let initialized;
|
|
1775
1775
|
if (!initialMatches) {
|
|
1776
|
-
// We need to run patchRoutesOnMiss in initialize()
|
|
1777
1776
|
initialized = false;
|
|
1778
1777
|
initialMatches = [];
|
|
1778
|
+
|
|
1779
|
+
// If partial hydration and fog of war is enabled, we will be running
|
|
1780
|
+
// `patchRoutesOnMiss` during hydration so include any partial matches as
|
|
1781
|
+
// the initial matches so we can properly render `HydrateFallback`'s
|
|
1782
|
+
if (future.v7_partialHydration) {
|
|
1783
|
+
let fogOfWar = checkFogOfWar(null, dataRoutes, init.history.location.pathname);
|
|
1784
|
+
if (fogOfWar.active && fogOfWar.matches) {
|
|
1785
|
+
initialMatches = fogOfWar.matches;
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1779
1788
|
} else if (initialMatches.some(m => m.route.lazy)) {
|
|
1780
1789
|
// All initialMatches need to be loaded before we're ready. If we have lazy
|
|
1781
1790
|
// functions around still then we'll need to run them in initialize()
|
|
@@ -1868,7 +1877,7 @@ function createRouter(init) {
|
|
|
1868
1877
|
|
|
1869
1878
|
// Use this internal array to capture fetcher loads that were cancelled by an
|
|
1870
1879
|
// action navigation and require revalidation
|
|
1871
|
-
let cancelledFetcherLoads =
|
|
1880
|
+
let cancelledFetcherLoads = new Set();
|
|
1872
1881
|
|
|
1873
1882
|
// AbortControllers for any in-flight fetchers
|
|
1874
1883
|
let fetchControllers = new Map();
|
|
@@ -2168,7 +2177,6 @@ function createRouter(init) {
|
|
|
2168
2177
|
isUninterruptedRevalidation = false;
|
|
2169
2178
|
isRevalidationRequired = false;
|
|
2170
2179
|
cancelledDeferredRoutes = [];
|
|
2171
|
-
cancelledFetcherLoads = [];
|
|
2172
2180
|
}
|
|
2173
2181
|
|
|
2174
2182
|
// Trigger a navigation event, which can either be a numerical POP or a PUSH
|
|
@@ -3264,7 +3272,7 @@ function createRouter(init) {
|
|
|
3264
3272
|
// Abort in-flight fetcher loads
|
|
3265
3273
|
fetchLoadMatches.forEach((_, key) => {
|
|
3266
3274
|
if (fetchControllers.has(key)) {
|
|
3267
|
-
cancelledFetcherLoads.
|
|
3275
|
+
cancelledFetcherLoads.add(key);
|
|
3268
3276
|
abortFetcher(key);
|
|
3269
3277
|
}
|
|
3270
3278
|
});
|
|
@@ -3318,6 +3326,7 @@ function createRouter(init) {
|
|
|
3318
3326
|
fetchReloadIds.delete(key);
|
|
3319
3327
|
fetchRedirectIds.delete(key);
|
|
3320
3328
|
deletedFetchers.delete(key);
|
|
3329
|
+
cancelledFetcherLoads.delete(key);
|
|
3321
3330
|
state.fetchers.delete(key);
|
|
3322
3331
|
}
|
|
3323
3332
|
function deleteFetcherAndUpdateState(key) {
|
|
@@ -3539,11 +3548,10 @@ function createRouter(init) {
|
|
|
3539
3548
|
matches: fogMatches || []
|
|
3540
3549
|
};
|
|
3541
3550
|
} else {
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
//
|
|
3545
|
-
//
|
|
3546
|
-
// around and find out
|
|
3551
|
+
if (Object.keys(matches[0].params).length > 0) {
|
|
3552
|
+
// If we matched a dynamic param or a splat, it might only be because
|
|
3553
|
+
// we haven't yet discovered other routes that would match with a
|
|
3554
|
+
// higher score. Call patchRoutesOnMiss just to be sure
|
|
3547
3555
|
let partialMatches = matchRoutesImpl(routesToUse, pathname, basename, true);
|
|
3548
3556
|
return {
|
|
3549
3557
|
active: true,
|
|
@@ -3559,7 +3567,6 @@ function createRouter(init) {
|
|
|
3559
3567
|
}
|
|
3560
3568
|
async function discoverRoutes(matches, pathname, signal) {
|
|
3561
3569
|
let partialMatches = matches;
|
|
3562
|
-
let route = partialMatches.length > 0 ? partialMatches[partialMatches.length - 1].route : null;
|
|
3563
3570
|
while (true) {
|
|
3564
3571
|
let isNonHMR = inFlightDataRoutes == null;
|
|
3565
3572
|
let routesToUse = inFlightDataRoutes || dataRoutes;
|
|
@@ -3588,51 +3595,22 @@ function createRouter(init) {
|
|
|
3588
3595
|
};
|
|
3589
3596
|
}
|
|
3590
3597
|
let newMatches = matchRoutes(routesToUse, pathname, basename);
|
|
3591
|
-
let matchedSplat = false;
|
|
3592
3598
|
if (newMatches) {
|
|
3593
|
-
let leafRoute = newMatches[newMatches.length - 1].route;
|
|
3594
|
-
if (leafRoute.index) {
|
|
3595
|
-
// If we found an index route, we can stop
|
|
3596
|
-
return {
|
|
3597
|
-
type: "success",
|
|
3598
|
-
matches: newMatches
|
|
3599
|
-
};
|
|
3600
|
-
}
|
|
3601
|
-
if (leafRoute.path && leafRoute.path.length > 0) {
|
|
3602
|
-
if (leafRoute.path === "*") {
|
|
3603
|
-
// If we found a splat route, we can't be sure there's not a
|
|
3604
|
-
// higher-scoring route down some partial matches trail so we need
|
|
3605
|
-
// to check that out
|
|
3606
|
-
matchedSplat = true;
|
|
3607
|
-
} else {
|
|
3608
|
-
// If we found a non-splat route, we can stop
|
|
3609
|
-
return {
|
|
3610
|
-
type: "success",
|
|
3611
|
-
matches: newMatches
|
|
3612
|
-
};
|
|
3613
|
-
}
|
|
3614
|
-
}
|
|
3615
|
-
}
|
|
3616
|
-
let newPartialMatches = matchRoutesImpl(routesToUse, pathname, basename, true);
|
|
3617
|
-
|
|
3618
|
-
// If we are no longer partially matching anything, this was either a
|
|
3619
|
-
// legit splat match above, or it's a 404. Also avoid loops if the
|
|
3620
|
-
// second pass results in the same partial matches
|
|
3621
|
-
if (!newPartialMatches || partialMatches.map(m => m.route.id).join("-") === newPartialMatches.map(m => m.route.id).join("-")) {
|
|
3622
3599
|
return {
|
|
3623
3600
|
type: "success",
|
|
3624
|
-
matches:
|
|
3601
|
+
matches: newMatches
|
|
3625
3602
|
};
|
|
3626
3603
|
}
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
if
|
|
3630
|
-
|
|
3604
|
+
let newPartialMatches = matchRoutesImpl(routesToUse, pathname, basename, true);
|
|
3605
|
+
|
|
3606
|
+
// Avoid loops if the second pass results in the same partial matches
|
|
3607
|
+
if (!newPartialMatches || partialMatches.length === newPartialMatches.length && partialMatches.every((m, i) => m.route.id === newPartialMatches[i].route.id)) {
|
|
3631
3608
|
return {
|
|
3632
3609
|
type: "success",
|
|
3633
|
-
matches:
|
|
3610
|
+
matches: null
|
|
3634
3611
|
};
|
|
3635
3612
|
}
|
|
3613
|
+
partialMatches = newPartialMatches;
|
|
3636
3614
|
}
|
|
3637
3615
|
}
|
|
3638
3616
|
function _internalSetRoutes(newRoutes) {
|
|
@@ -4433,8 +4411,9 @@ function getMatchesToLoad(history, state, matches, submission, location, isIniti
|
|
|
4433
4411
|
if (fetchRedirectIds.has(key)) {
|
|
4434
4412
|
// Never trigger a revalidation of an actively redirecting fetcher
|
|
4435
4413
|
shouldRevalidate = false;
|
|
4436
|
-
} else if (cancelledFetcherLoads.
|
|
4437
|
-
// Always
|
|
4414
|
+
} else if (cancelledFetcherLoads.has(key)) {
|
|
4415
|
+
// Always mark for revalidation if the fetcher was cancelled
|
|
4416
|
+
cancelledFetcherLoads.delete(key);
|
|
4438
4417
|
shouldRevalidate = true;
|
|
4439
4418
|
} else if (fetcher && fetcher.state !== "idle" && fetcher.data === undefined) {
|
|
4440
4419
|
// If the fetcher hasn't ever completed loading yet, then this isn't a
|