react-router 7.9.6 → 7.10.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 +75 -10
- package/dist/development/{browser-BbBXFHbO.d.ts → browser-BpxEZgZC.d.ts} +1 -1
- package/dist/development/{browser-C07r42Tt.d.mts → browser-C5z6FZmz.d.mts} +1 -1
- package/dist/development/{chunk-4WY6JWTD.mjs → chunk-GIMUO62I.mjs} +208 -221
- package/dist/development/{chunk-AMVS5XVJ.js → chunk-KQLPIZ7E.js} +201 -258
- package/dist/development/{chunk-PZWDWJAY.js → chunk-RHWHYDYZ.js} +7 -7
- package/dist/development/{chunk-G3INQAYP.mjs → chunk-V5RTLP6E.mjs} +15 -5
- package/dist/development/{chunk-O4JVZSOY.js → chunk-XHWAND4X.js} +167 -123
- package/dist/development/dom-export.d.mts +29 -10
- package/dist/development/dom-export.d.ts +29 -10
- package/dist/development/dom-export.js +158 -103
- package/dist/development/dom-export.mjs +133 -79
- package/dist/{production/index-react-server-client-Da3kmxNd.d.ts → development/index-react-server-client-CCjKYJTH.d.ts} +75 -180
- package/dist/development/{index-react-server-client-rcoGPJhU.d.mts → index-react-server-client-CipGfVBI.d.mts} +75 -180
- package/dist/development/index-react-server-client.d.mts +2 -2
- package/dist/development/index-react-server-client.d.ts +2 -2
- package/dist/development/index-react-server-client.js +4 -4
- package/dist/development/index-react-server-client.mjs +2 -2
- package/dist/development/index-react-server.d.mts +19 -4
- package/dist/development/index-react-server.d.ts +19 -4
- package/dist/development/index-react-server.js +30 -24
- package/dist/development/index-react-server.mjs +30 -24
- package/dist/development/index.d.mts +19 -15
- package/dist/development/index.d.ts +19 -15
- package/dist/development/index.js +92 -82
- package/dist/development/index.mjs +3 -3
- package/dist/{production/instrumentation-Unc20tLk.d.ts → development/instrumentation-BB0wRuqz.d.ts} +93 -11
- package/dist/development/lib/types/internal.d.mts +2 -2
- package/dist/development/lib/types/internal.d.ts +2 -2
- package/dist/development/lib/types/internal.js +1 -1
- package/dist/development/lib/types/internal.mjs +1 -1
- package/dist/development/{register-QkB3HGjm.d.mts → register-C1RwVJAt.d.mts} +1 -1
- package/dist/development/{register-BpU9rFBJ.d.ts → register-ODDAAYlf.d.ts} +1 -1
- package/dist/development/{router-CAvh_Drx.d.mts → router-CwNp5l9u.d.mts} +93 -11
- package/dist/production/{browser-BbBXFHbO.d.ts → browser-BpxEZgZC.d.ts} +1 -1
- package/dist/production/{browser-C07r42Tt.d.mts → browser-C5z6FZmz.d.mts} +1 -1
- package/dist/production/{chunk-QN64DHI4.js → chunk-3MVZKESN.js} +167 -123
- package/dist/production/{chunk-FUSXQSWG.mjs → chunk-7F5XUDXM.mjs} +208 -221
- package/dist/production/{chunk-EAIF67OW.js → chunk-C7S4I3K5.js} +201 -258
- package/dist/production/{chunk-FDUMZGKM.mjs → chunk-ISOIFGFA.mjs} +15 -5
- package/dist/production/{chunk-G5A35OQU.js → chunk-YU3WNS3T.js} +7 -7
- package/dist/production/dom-export.d.mts +29 -10
- package/dist/production/dom-export.d.ts +29 -10
- package/dist/production/dom-export.js +158 -103
- package/dist/production/dom-export.mjs +133 -79
- package/dist/{development/index-react-server-client-Da3kmxNd.d.ts → production/index-react-server-client-CCjKYJTH.d.ts} +75 -180
- package/dist/production/{index-react-server-client-rcoGPJhU.d.mts → index-react-server-client-CipGfVBI.d.mts} +75 -180
- package/dist/production/index-react-server-client.d.mts +2 -2
- package/dist/production/index-react-server-client.d.ts +2 -2
- package/dist/production/index-react-server-client.js +4 -4
- package/dist/production/index-react-server-client.mjs +2 -2
- package/dist/production/index-react-server.d.mts +19 -4
- package/dist/production/index-react-server.d.ts +19 -4
- package/dist/production/index-react-server.js +30 -24
- package/dist/production/index-react-server.mjs +30 -24
- package/dist/production/index.d.mts +19 -15
- package/dist/production/index.d.ts +19 -15
- package/dist/production/index.js +92 -82
- package/dist/production/index.mjs +3 -3
- package/dist/{development/instrumentation-Unc20tLk.d.ts → production/instrumentation-BB0wRuqz.d.ts} +93 -11
- package/dist/production/lib/types/internal.d.mts +2 -2
- package/dist/production/lib/types/internal.d.ts +2 -2
- package/dist/production/lib/types/internal.js +1 -1
- package/dist/production/lib/types/internal.mjs +1 -1
- package/dist/production/{register-QkB3HGjm.d.mts → register-C1RwVJAt.d.mts} +1 -1
- package/dist/production/{register-BpU9rFBJ.d.ts → register-ODDAAYlf.d.ts} +1 -1
- package/dist/production/{router-CAvh_Drx.d.mts → router-CwNp5l9u.d.mts} +93 -11
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* react-router v7.
|
|
2
|
+
* react-router v7.10.0-pre.1
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
deserializeErrors,
|
|
15
15
|
getHydrationData,
|
|
16
16
|
populateRSCRouteModules
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-V5RTLP6E.mjs";
|
|
18
18
|
import {
|
|
19
19
|
CRITICAL_CSS_DATA_ATTRIBUTE,
|
|
20
20
|
ErrorResponseImpl,
|
|
@@ -22,7 +22,6 @@ import {
|
|
|
22
22
|
RSCRouterContext,
|
|
23
23
|
RemixErrorBoundary,
|
|
24
24
|
RouterProvider,
|
|
25
|
-
UNSTABLE_TransitionEnabledRouterProvider,
|
|
26
25
|
createBrowserHistory,
|
|
27
26
|
createClientRoutes,
|
|
28
27
|
createClientRoutesWithHMRRevalidationOptOut,
|
|
@@ -43,7 +42,7 @@ import {
|
|
|
43
42
|
singleFetchUrl,
|
|
44
43
|
stripIndexParam,
|
|
45
44
|
useFogOFWarDiscovery
|
|
46
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-GIMUO62I.mjs";
|
|
47
46
|
|
|
48
47
|
// lib/dom-export/dom-router-provider.tsx
|
|
49
48
|
import * as React from "react";
|
|
@@ -245,6 +244,7 @@ function HydratedRouter(props) {
|
|
|
245
244
|
RouterProvider2,
|
|
246
245
|
{
|
|
247
246
|
router,
|
|
247
|
+
unstable_useTransitions: props.unstable_useTransitions,
|
|
248
248
|
unstable_onError: props.unstable_onError
|
|
249
249
|
}
|
|
250
250
|
))
|
|
@@ -283,66 +283,68 @@ function createCallServer({
|
|
|
283
283
|
temporaryReferences
|
|
284
284
|
});
|
|
285
285
|
});
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
}
|
|
294
|
-
return () => {
|
|
295
|
-
globalVar.__reactRouterDataRouter.navigate(payload.location, {
|
|
296
|
-
replace: payload.replace
|
|
297
|
-
});
|
|
298
|
-
};
|
|
299
|
-
}
|
|
300
|
-
if (payload.type !== "action") {
|
|
301
|
-
throw new Error("Unexpected payload type");
|
|
302
|
-
}
|
|
303
|
-
const rerender = await payload.rerender;
|
|
304
|
-
if (rerender && landedActionId < actionId && globalVar.__routerActionID <= actionId) {
|
|
305
|
-
if (rerender.type === "redirect") {
|
|
306
|
-
if (rerender.reload || isExternalLocation(rerender.location)) {
|
|
307
|
-
window.location.href = rerender.location;
|
|
286
|
+
React3.startTransition(
|
|
287
|
+
() => (
|
|
288
|
+
// @ts-expect-error - Needs React 19 types
|
|
289
|
+
Promise.resolve(payloadPromise).then(async (payload) => {
|
|
290
|
+
if (payload.type === "redirect") {
|
|
291
|
+
if (payload.reload || isExternalLocation(payload.location)) {
|
|
292
|
+
window.location.href = payload.location;
|
|
308
293
|
return;
|
|
309
294
|
}
|
|
310
|
-
|
|
311
|
-
globalVar.__reactRouterDataRouter.navigate(
|
|
312
|
-
replace:
|
|
295
|
+
React3.startTransition(() => {
|
|
296
|
+
globalVar.__reactRouterDataRouter.navigate(payload.location, {
|
|
297
|
+
replace: payload.replace
|
|
313
298
|
});
|
|
314
|
-
};
|
|
299
|
+
});
|
|
300
|
+
return;
|
|
315
301
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
302
|
+
if (payload.type !== "action") {
|
|
303
|
+
throw new Error("Unexpected payload type");
|
|
304
|
+
}
|
|
305
|
+
const rerender = await payload.rerender;
|
|
306
|
+
if (rerender && landedActionId < actionId && globalVar.__routerActionID <= actionId) {
|
|
307
|
+
if (rerender.type === "redirect") {
|
|
308
|
+
if (rerender.reload || isExternalLocation(rerender.location)) {
|
|
309
|
+
window.location.href = rerender.location;
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
React3.startTransition(() => {
|
|
313
|
+
globalVar.__reactRouterDataRouter.navigate(rerender.location, {
|
|
314
|
+
replace: rerender.replace
|
|
315
|
+
});
|
|
316
|
+
});
|
|
317
|
+
return;
|
|
325
318
|
}
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
globalVar.__reactRouterDataRouter.state.errors,
|
|
336
|
-
rerender.errors
|
|
337
|
-
) : null
|
|
319
|
+
React3.startTransition(() => {
|
|
320
|
+
let lastMatch;
|
|
321
|
+
for (const match of rerender.matches) {
|
|
322
|
+
globalVar.__reactRouterDataRouter.patchRoutes(
|
|
323
|
+
lastMatch?.id ?? null,
|
|
324
|
+
[createRouteFromServerManifest(match)],
|
|
325
|
+
true
|
|
326
|
+
);
|
|
327
|
+
lastMatch = match;
|
|
338
328
|
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
329
|
+
window.__reactRouterDataRouter._internalSetStateDoNotUseOrYouWillBreakYourApp(
|
|
330
|
+
{
|
|
331
|
+
loaderData: Object.assign(
|
|
332
|
+
{},
|
|
333
|
+
globalVar.__reactRouterDataRouter.state.loaderData,
|
|
334
|
+
rerender.loaderData
|
|
335
|
+
),
|
|
336
|
+
errors: rerender.errors ? Object.assign(
|
|
337
|
+
{},
|
|
338
|
+
globalVar.__reactRouterDataRouter.state.errors,
|
|
339
|
+
rerender.errors
|
|
340
|
+
) : null
|
|
341
|
+
}
|
|
342
|
+
);
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
}).catch(() => {
|
|
346
|
+
})
|
|
347
|
+
)
|
|
346
348
|
);
|
|
347
349
|
return payloadPromise.then((payload) => {
|
|
348
350
|
if (payload.type !== "action" && payload.type !== "redirect") {
|
|
@@ -541,18 +543,20 @@ function getRSCSingleFetchDataStrategy(getRouter, ssr, basename, createFromReada
|
|
|
541
543
|
}
|
|
542
544
|
renderedRoutesById.get(route.id).push(route);
|
|
543
545
|
}
|
|
544
|
-
|
|
545
|
-
const
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
546
|
+
React3.startTransition(() => {
|
|
547
|
+
for (const match of args.matches) {
|
|
548
|
+
const renderedRoutes = renderedRoutesById.get(match.route.id);
|
|
549
|
+
if (renderedRoutes) {
|
|
550
|
+
for (const rendered of renderedRoutes) {
|
|
551
|
+
window.__reactRouterDataRouter.patchRoutes(
|
|
552
|
+
rendered.parentId ?? null,
|
|
553
|
+
[createRouteFromServerManifest(rendered)],
|
|
554
|
+
true
|
|
555
|
+
);
|
|
556
|
+
}
|
|
553
557
|
}
|
|
554
558
|
}
|
|
555
|
-
}
|
|
559
|
+
});
|
|
556
560
|
return results;
|
|
557
561
|
});
|
|
558
562
|
}
|
|
@@ -638,14 +642,29 @@ function RSCHydratedRouter({
|
|
|
638
642
|
globalVar.__reactRouterDataRouter.initialize();
|
|
639
643
|
}
|
|
640
644
|
}, []);
|
|
641
|
-
let [
|
|
645
|
+
let [{ routes, state }, setState] = React3.useState(() => ({
|
|
646
|
+
routes: cloneRoutes(router2.routes),
|
|
647
|
+
state: router2.state
|
|
648
|
+
}));
|
|
642
649
|
React3.useLayoutEffect(
|
|
643
650
|
() => router2.subscribe((newState) => {
|
|
644
|
-
if (
|
|
645
|
-
|
|
646
|
-
|
|
651
|
+
if (diffRoutes(router2.routes, routes))
|
|
652
|
+
React3.startTransition(() => {
|
|
653
|
+
setState({
|
|
654
|
+
routes: cloneRoutes(router2.routes),
|
|
655
|
+
state: newState
|
|
656
|
+
});
|
|
657
|
+
});
|
|
658
|
+
}),
|
|
659
|
+
[router2.subscribe, routes, router2]
|
|
660
|
+
);
|
|
661
|
+
const transitionEnabledRouter = React3.useMemo(
|
|
662
|
+
() => ({
|
|
663
|
+
...router2,
|
|
664
|
+
state,
|
|
665
|
+
routes
|
|
647
666
|
}),
|
|
648
|
-
[router2,
|
|
667
|
+
[router2, routes, state]
|
|
649
668
|
);
|
|
650
669
|
React3.useEffect(() => {
|
|
651
670
|
if (routeDiscovery === "lazy" || // @ts-expect-error - TS doesn't know about this yet
|
|
@@ -716,7 +735,14 @@ function RSCHydratedRouter({
|
|
|
716
735
|
routeDiscovery: { mode: "lazy", manifestPath: "/__manifest" },
|
|
717
736
|
routeModules
|
|
718
737
|
};
|
|
719
|
-
return /* @__PURE__ */ React3.createElement(RSCRouterContext.Provider, { value: true }, /* @__PURE__ */ React3.createElement(RSCRouterGlobalErrorBoundary, { location:
|
|
738
|
+
return /* @__PURE__ */ React3.createElement(RSCRouterContext.Provider, { value: true }, /* @__PURE__ */ React3.createElement(RSCRouterGlobalErrorBoundary, { location: state.location }, /* @__PURE__ */ React3.createElement(FrameworkContext.Provider, { value: frameworkContext }, /* @__PURE__ */ React3.createElement(
|
|
739
|
+
RouterProvider,
|
|
740
|
+
{
|
|
741
|
+
router: transitionEnabledRouter,
|
|
742
|
+
flushSync: ReactDOM2.flushSync,
|
|
743
|
+
unstable_useTransitions: true
|
|
744
|
+
}
|
|
745
|
+
))));
|
|
720
746
|
}
|
|
721
747
|
function createRouteFromServerManifest(match, payload) {
|
|
722
748
|
let hasInitialData = payload && match.id in payload.loaderData;
|
|
@@ -852,11 +878,13 @@ async function fetchAndApplyManifestPatches(paths, createFromReadableStream, fet
|
|
|
852
878
|
throw new Error("Failed to patch routes");
|
|
853
879
|
}
|
|
854
880
|
paths.forEach((p) => addToFifoQueue(p, discoveredPaths));
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
881
|
+
React3.startTransition(() => {
|
|
882
|
+
payload.patches.forEach((p) => {
|
|
883
|
+
window.__reactRouterDataRouter.patchRoutes(
|
|
884
|
+
p.parentId ?? null,
|
|
885
|
+
[createRouteFromServerManifest(p)]
|
|
886
|
+
);
|
|
887
|
+
});
|
|
860
888
|
});
|
|
861
889
|
}
|
|
862
890
|
function addToFifoQueue(path, queue) {
|
|
@@ -877,6 +905,32 @@ function isExternalLocation(location2) {
|
|
|
877
905
|
const newLocation = new URL(location2, window.location.href);
|
|
878
906
|
return newLocation.origin !== window.location.origin;
|
|
879
907
|
}
|
|
908
|
+
function cloneRoutes(routes) {
|
|
909
|
+
if (!routes) return void 0;
|
|
910
|
+
return routes.map((route) => ({
|
|
911
|
+
...route,
|
|
912
|
+
children: cloneRoutes(route.children)
|
|
913
|
+
}));
|
|
914
|
+
}
|
|
915
|
+
function diffRoutes(a, b) {
|
|
916
|
+
if (a.length !== b.length) return true;
|
|
917
|
+
return a.some((route, index) => {
|
|
918
|
+
if (route.element !== b[index].element) return true;
|
|
919
|
+
if (route.errorElement !== b[index].errorElement)
|
|
920
|
+
return true;
|
|
921
|
+
if (route.hydrateFallbackElement !== b[index].hydrateFallbackElement)
|
|
922
|
+
return true;
|
|
923
|
+
if (route.hasErrorBoundary !== b[index].hasErrorBoundary)
|
|
924
|
+
return true;
|
|
925
|
+
if (route.hasLoader !== b[index].hasLoader) return true;
|
|
926
|
+
if (route.hasClientLoader !== b[index].hasClientLoader)
|
|
927
|
+
return true;
|
|
928
|
+
if (route.hasAction !== b[index].hasAction) return true;
|
|
929
|
+
if (route.hasClientAction !== b[index].hasClientAction)
|
|
930
|
+
return true;
|
|
931
|
+
return diffRoutes(route.children || [], b[index].children || []);
|
|
932
|
+
});
|
|
933
|
+
}
|
|
880
934
|
|
|
881
935
|
// lib/rsc/html-stream/browser.ts
|
|
882
936
|
function getRSCStream() {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { bE as RouteManifest, o as RouteModules, Q as HydrationState, a1 as DataRouteObject, a as ClientLoaderFunction, a5 as StaticHandlerContext, bF as ServerRouteModule, q as MiddlewareEnabled, c as RouterContextProvider, r as AppLoadContext, al as LoaderFunctionArgs, ac as ActionFunctionArgs, au as unstable_ServerInstrumentation, aj as HTMLFormMethod, ah as FormEncType, w as RelativeRoutingType, bh as PageLinkDescriptor, T as To, bG as History, a4 as GetScrollRestorationKeyFunction, e as RouterInit, bH as FutureConfig$1, u as unstable_ClientInstrumentation, p as DataStrategyFunction, a0 as PatchRoutesOnNavigationFunction, s as NavigateOptions, a6 as Fetcher, K as RouteObject, n as Router, v as SerializeFrom, B as BlockerFunction, L as Location, bI as CreateStaticHandlerOptions$1, a2 as StaticHandler } from './instrumentation-
|
|
1
|
+
import { bE as RouteManifest, o as RouteModules, Q as HydrationState, a1 as DataRouteObject, a as ClientLoaderFunction, a5 as StaticHandlerContext, bF as ServerRouteModule, q as MiddlewareEnabled, c as RouterContextProvider, r as AppLoadContext, al as LoaderFunctionArgs, ac as ActionFunctionArgs, au as unstable_ServerInstrumentation, aj as HTMLFormMethod, ah as FormEncType, w as RelativeRoutingType, bh as PageLinkDescriptor, T as To, bG as History, a4 as GetScrollRestorationKeyFunction, e as RouterInit, bH as FutureConfig$1, u as unstable_ClientInstrumentation, p as DataStrategyFunction, a0 as PatchRoutesOnNavigationFunction, s as NavigateOptions, a6 as Fetcher, K as RouteObject, n as Router, v as SerializeFrom, B as BlockerFunction, L as Location, bI as CreateStaticHandlerOptions$1, a2 as StaticHandler } from './instrumentation-BB0wRuqz.js';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
|
|
4
4
|
interface Route {
|
|
@@ -536,7 +536,7 @@ interface DOMRouterOpts {
|
|
|
536
536
|
* added routes via `route.lazy` or `patchRoutesOnNavigation`). This is
|
|
537
537
|
* mostly useful for observability such as wrapping navigations, fetches,
|
|
538
538
|
* as well as route loaders/actions/middlewares with logging and/or performance
|
|
539
|
-
* tracing.
|
|
539
|
+
* tracing. See the [docs](../../how-to/instrumentation) for more information.
|
|
540
540
|
*
|
|
541
541
|
* ```tsx
|
|
542
542
|
* let router = createBrowserRouter(routes, {
|
|
@@ -580,189 +580,32 @@ interface DOMRouterOpts {
|
|
|
580
580
|
*/
|
|
581
581
|
unstable_instrumentations?: unstable_ClientInstrumentation[];
|
|
582
582
|
/**
|
|
583
|
-
* Override the default data strategy of running loaders in parallel
|
|
584
|
-
*
|
|
585
|
-
*
|
|
586
|
-
* <docs-warning>This is a low-level API intended for advanced use-cases. This
|
|
587
|
-
* overrides React Router's internal handling of
|
|
588
|
-
* [`action`](../../start/data/route-object#action)/[`loader`](../../start/data/route-object#loader)
|
|
589
|
-
* execution, and if done incorrectly will break your app code. Please use
|
|
590
|
-
* with caution and perform the appropriate testing.</docs-warning>
|
|
591
|
-
*
|
|
592
|
-
* By default, React Router is opinionated about how your data is loaded/submitted -
|
|
593
|
-
* and most notably, executes all of your [`loader`](../../start/data/route-object#loader)s
|
|
594
|
-
* in parallel for optimal data fetching. While we think this is the right
|
|
595
|
-
* behavior for most use-cases, we realize that there is no "one size fits all"
|
|
596
|
-
* solution when it comes to data fetching for the wide landscape of
|
|
597
|
-
* application requirements.
|
|
598
|
-
*
|
|
599
|
-
* The `dataStrategy` option gives you full control over how your [`action`](../../start/data/route-object#action)s
|
|
600
|
-
* and [`loader`](../../start/data/route-object#loader)s are executed and lays
|
|
601
|
-
* the foundation to build in more advanced APIs such as middleware, context,
|
|
602
|
-
* and caching layers. Over time, we expect that we'll leverage this API
|
|
603
|
-
* internally to bring more first class APIs to React Router, but until then
|
|
604
|
-
* (and beyond), this is your way to add more advanced functionality for your
|
|
605
|
-
* application's data needs.
|
|
606
|
-
*
|
|
607
|
-
* The `dataStrategy` function should return a key/value-object of
|
|
608
|
-
* `routeId` -> {@link DataStrategyResult} and should include entries for any
|
|
609
|
-
* routes where a handler was executed. A `DataStrategyResult` indicates if
|
|
610
|
-
* the handler was successful or not based on the `DataStrategyResult.type`
|
|
611
|
-
* field. If the returned `DataStrategyResult.result` is a [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response),
|
|
612
|
-
* React Router will unwrap it for you (via [`res.json`](https://developer.mozilla.org/en-US/docs/Web/API/Response/json)
|
|
613
|
-
* or [`res.text`](https://developer.mozilla.org/en-US/docs/Web/API/Response/text)).
|
|
614
|
-
* If you need to do custom decoding of a [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response)
|
|
615
|
-
* but want to preserve the status code, you can use the `data` utility to
|
|
616
|
-
* return your decoded data along with a `ResponseInit`.
|
|
617
|
-
*
|
|
618
|
-
* <details>
|
|
619
|
-
* <summary><b>Example <code>dataStrategy</code> Use Cases</b></summary>
|
|
620
|
-
*
|
|
621
|
-
* **Adding logging**
|
|
622
|
-
*
|
|
623
|
-
* In the simplest case, let's look at hooking into this API to add some logging
|
|
624
|
-
* for when our route [`action`](../../start/data/route-object#action)s/[`loader`](../../start/data/route-object#loader)s
|
|
625
|
-
* execute:
|
|
583
|
+
* Override the default data strategy of running loaders in parallel -
|
|
584
|
+
* see the [docs](../../how-to/data-strategy) for more information.
|
|
626
585
|
*
|
|
627
586
|
* ```tsx
|
|
628
587
|
* let router = createBrowserRouter(routes, {
|
|
629
|
-
* async dataStrategy({
|
|
630
|
-
*
|
|
631
|
-
*
|
|
632
|
-
*
|
|
633
|
-
*
|
|
634
|
-
*
|
|
635
|
-
*
|
|
636
|
-
* })
|
|
588
|
+
* async dataStrategy({
|
|
589
|
+
* matches,
|
|
590
|
+
* request,
|
|
591
|
+
* runClientMiddleware,
|
|
592
|
+
* }) {
|
|
593
|
+
* const matchesToLoad = matches.filter((m) =>
|
|
594
|
+
* m.shouldCallHandler(),
|
|
637
595
|
* );
|
|
638
|
-
* return results;
|
|
639
|
-
* },
|
|
640
|
-
* });
|
|
641
|
-
* ```
|
|
642
|
-
*
|
|
643
|
-
* **Middleware**
|
|
644
|
-
*
|
|
645
|
-
* Let's define a middleware on each route via [`handle`](../../start/data/route-object#handle)
|
|
646
|
-
* and call middleware sequentially first, then call all
|
|
647
|
-
* [`loader`](../../start/data/route-object#loader)s in parallel - providing
|
|
648
|
-
* any data made available via the middleware:
|
|
649
|
-
*
|
|
650
|
-
* ```ts
|
|
651
|
-
* const routes = [
|
|
652
|
-
* {
|
|
653
|
-
* id: "parent",
|
|
654
|
-
* path: "/parent",
|
|
655
|
-
* loader({ request }, context) {
|
|
656
|
-
* // ...
|
|
657
|
-
* },
|
|
658
|
-
* handle: {
|
|
659
|
-
* async middleware({ request }, context) {
|
|
660
|
-
* context.parent = "PARENT MIDDLEWARE";
|
|
661
|
-
* },
|
|
662
|
-
* },
|
|
663
|
-
* children: [
|
|
664
|
-
* {
|
|
665
|
-
* id: "child",
|
|
666
|
-
* path: "child",
|
|
667
|
-
* loader({ request }, context) {
|
|
668
|
-
* // ...
|
|
669
|
-
* },
|
|
670
|
-
* handle: {
|
|
671
|
-
* async middleware({ request }, context) {
|
|
672
|
-
* context.child = "CHILD MIDDLEWARE";
|
|
673
|
-
* },
|
|
674
|
-
* },
|
|
675
|
-
* },
|
|
676
|
-
* ],
|
|
677
|
-
* },
|
|
678
|
-
* ];
|
|
679
596
|
*
|
|
680
|
-
*
|
|
681
|
-
*
|
|
682
|
-
*
|
|
683
|
-
*
|
|
684
|
-
*
|
|
685
|
-
* if (match.route.handle?.middleware) {
|
|
686
|
-
* await match.route.handle.middleware(
|
|
687
|
-
* { request, params },
|
|
688
|
-
* context
|
|
689
|
-
* );
|
|
690
|
-
* }
|
|
691
|
-
* }
|
|
692
|
-
*
|
|
693
|
-
* // Run loaders in parallel with the `context` value
|
|
694
|
-
* let matchesToLoad = matches.filter((m) => m.shouldLoad);
|
|
695
|
-
* let results = await Promise.all(
|
|
696
|
-
* matchesToLoad.map((match, i) =>
|
|
697
|
-
* match.resolve((handler) => {
|
|
698
|
-
* // Whatever you pass to `handler` will be passed as the 2nd parameter
|
|
699
|
-
* // to your loader/action
|
|
700
|
-
* return handler(context);
|
|
701
|
-
* })
|
|
702
|
-
* )
|
|
703
|
-
* );
|
|
704
|
-
* return results.reduce(
|
|
705
|
-
* (acc, result, i) =>
|
|
706
|
-
* Object.assign(acc, {
|
|
707
|
-
* [matchesToLoad[i].route.id]: result,
|
|
597
|
+
* const results: Record<string, DataStrategyResult> = {};
|
|
598
|
+
* await runClientMiddleware(() =>
|
|
599
|
+
* Promise.all(
|
|
600
|
+
* matchesToLoad.map(async (match) => {
|
|
601
|
+
* results[match.route.id] = await match.resolve();
|
|
708
602
|
* }),
|
|
709
|
-
*
|
|
603
|
+
* ),
|
|
710
604
|
* );
|
|
711
|
-
* },
|
|
712
|
-
* });
|
|
713
|
-
* ```
|
|
714
|
-
*
|
|
715
|
-
* **Custom Handler**
|
|
716
|
-
*
|
|
717
|
-
* It's also possible you don't even want to define a [`loader`](../../start/data/route-object#loader)
|
|
718
|
-
* implementation at the route level. Maybe you want to just determine the
|
|
719
|
-
* routes and issue a single GraphQL request for all of your data? You can do
|
|
720
|
-
* that by setting your `route.loader=true` so it qualifies as "having a
|
|
721
|
-
* loader", and then store GQL fragments on `route.handle`:
|
|
722
|
-
*
|
|
723
|
-
* ```ts
|
|
724
|
-
* const routes = [
|
|
725
|
-
* {
|
|
726
|
-
* id: "parent",
|
|
727
|
-
* path: "/parent",
|
|
728
|
-
* loader: true,
|
|
729
|
-
* handle: {
|
|
730
|
-
* gql: gql`
|
|
731
|
-
* fragment Parent on Whatever {
|
|
732
|
-
* parentField
|
|
733
|
-
* }
|
|
734
|
-
* `,
|
|
735
|
-
* },
|
|
736
|
-
* children: [
|
|
737
|
-
* {
|
|
738
|
-
* id: "child",
|
|
739
|
-
* path: "child",
|
|
740
|
-
* loader: true,
|
|
741
|
-
* handle: {
|
|
742
|
-
* gql: gql`
|
|
743
|
-
* fragment Child on Whatever {
|
|
744
|
-
* childField
|
|
745
|
-
* }
|
|
746
|
-
* `,
|
|
747
|
-
* },
|
|
748
|
-
* },
|
|
749
|
-
* ],
|
|
750
|
-
* },
|
|
751
|
-
* ];
|
|
752
|
-
*
|
|
753
|
-
* let router = createBrowserRouter(routes, {
|
|
754
|
-
* async dataStrategy({ matches, params, request }) {
|
|
755
|
-
* // Compose route fragments into a single GQL payload
|
|
756
|
-
* let gql = getFragmentsFromRouteHandles(matches);
|
|
757
|
-
* let data = await fetchGql(gql);
|
|
758
|
-
* // Parse results back out into individual route level `DataStrategyResult`'s
|
|
759
|
-
* // keyed by `routeId`
|
|
760
|
-
* let results = parseResultsFromGql(data);
|
|
761
605
|
* return results;
|
|
762
606
|
* },
|
|
763
607
|
* });
|
|
764
608
|
* ```
|
|
765
|
-
*</details>
|
|
766
609
|
*/
|
|
767
610
|
dataStrategy?: DataStrategyFunction;
|
|
768
611
|
/**
|
|
@@ -1122,6 +965,21 @@ interface BrowserRouterProps {
|
|
|
1122
965
|
* {@link Route | `<Route>`} components describing your route configuration
|
|
1123
966
|
*/
|
|
1124
967
|
children?: React.ReactNode;
|
|
968
|
+
/**
|
|
969
|
+
* Control whether router state updates are internally wrapped in
|
|
970
|
+
* [`React.startTransition`](https://react.dev/reference/react/startTransition).
|
|
971
|
+
*
|
|
972
|
+
* - When left `undefined`, all router state updates are wrapped in
|
|
973
|
+
* `React.startTransition`
|
|
974
|
+
* - When set to `true`, {@link Link} and {@link Form} navigations will be wrapped
|
|
975
|
+
* in `React.startTransition` and all router state updates are wrapped in
|
|
976
|
+
* `React.startTransition`
|
|
977
|
+
* - When set to `false`, the router will not leverage `React.startTransition`
|
|
978
|
+
* on any navigations or state changes.
|
|
979
|
+
*
|
|
980
|
+
* For more information, please see the [docs](https://reactrouter.com/explanation/react-transitions).
|
|
981
|
+
*/
|
|
982
|
+
unstable_useTransitions?: boolean;
|
|
1125
983
|
/**
|
|
1126
984
|
* [`Window`](https://developer.mozilla.org/en-US/docs/Web/API/Window) object
|
|
1127
985
|
* override. Defaults to the global `window` instance
|
|
@@ -1138,11 +996,12 @@ interface BrowserRouterProps {
|
|
|
1138
996
|
* @param props Props
|
|
1139
997
|
* @param {BrowserRouterProps.basename} props.basename n/a
|
|
1140
998
|
* @param {BrowserRouterProps.children} props.children n/a
|
|
999
|
+
* @param {BrowserRouterProps.unstable_useTransitions} props.unstable_useTransitions n/a
|
|
1141
1000
|
* @param {BrowserRouterProps.window} props.window n/a
|
|
1142
1001
|
* @returns A declarative {@link Router | `<Router>`} using the browser [`History`](https://developer.mozilla.org/en-US/docs/Web/API/History)
|
|
1143
1002
|
* API for client-side routing.
|
|
1144
1003
|
*/
|
|
1145
|
-
declare function BrowserRouter({ basename, children, window, }: BrowserRouterProps): React.JSX.Element;
|
|
1004
|
+
declare function BrowserRouter({ basename, children, unstable_useTransitions, window, }: BrowserRouterProps): React.JSX.Element;
|
|
1146
1005
|
/**
|
|
1147
1006
|
* @category Types
|
|
1148
1007
|
*/
|
|
@@ -1155,6 +1014,21 @@ interface HashRouterProps {
|
|
|
1155
1014
|
* {@link Route | `<Route>`} components describing your route configuration
|
|
1156
1015
|
*/
|
|
1157
1016
|
children?: React.ReactNode;
|
|
1017
|
+
/**
|
|
1018
|
+
* Control whether router state updates are internally wrapped in
|
|
1019
|
+
* [`React.startTransition`](https://react.dev/reference/react/startTransition).
|
|
1020
|
+
*
|
|
1021
|
+
* - When left `undefined`, all router state updates are wrapped in
|
|
1022
|
+
* `React.startTransition`
|
|
1023
|
+
* - When set to `true`, {@link Link} and {@link Form} navigations will be wrapped
|
|
1024
|
+
* in `React.startTransition` and all router state updates are wrapped in
|
|
1025
|
+
* `React.startTransition`
|
|
1026
|
+
* - When set to `false`, the router will not leverage `React.startTransition`
|
|
1027
|
+
* on any navigations or state changes.
|
|
1028
|
+
*
|
|
1029
|
+
* For more information, please see the [docs](https://reactrouter.com/explanation/react-transitions).
|
|
1030
|
+
*/
|
|
1031
|
+
unstable_useTransitions?: boolean;
|
|
1158
1032
|
/**
|
|
1159
1033
|
* [`Window`](https://developer.mozilla.org/en-US/docs/Web/API/Window) object
|
|
1160
1034
|
* override. Defaults to the global `window` instance
|
|
@@ -1172,11 +1046,12 @@ interface HashRouterProps {
|
|
|
1172
1046
|
* @param props Props
|
|
1173
1047
|
* @param {HashRouterProps.basename} props.basename n/a
|
|
1174
1048
|
* @param {HashRouterProps.children} props.children n/a
|
|
1049
|
+
* @param {HashRouterProps.unstable_useTransitions} props.unstable_useTransitions n/a
|
|
1175
1050
|
* @param {HashRouterProps.window} props.window n/a
|
|
1176
1051
|
* @returns A declarative {@link Router | `<Router>`} using the URL [`hash`](https://developer.mozilla.org/en-US/docs/Web/API/URL/hash)
|
|
1177
1052
|
* for client-side routing.
|
|
1178
1053
|
*/
|
|
1179
|
-
declare function HashRouter({ basename, children, window }: HashRouterProps): React.JSX.Element;
|
|
1054
|
+
declare function HashRouter({ basename, children, unstable_useTransitions, window, }: HashRouterProps): React.JSX.Element;
|
|
1180
1055
|
/**
|
|
1181
1056
|
* @category Types
|
|
1182
1057
|
*/
|
|
@@ -1193,6 +1068,21 @@ interface HistoryRouterProps {
|
|
|
1193
1068
|
* A {@link History} implementation for use by the router
|
|
1194
1069
|
*/
|
|
1195
1070
|
history: History;
|
|
1071
|
+
/**
|
|
1072
|
+
* Control whether router state updates are internally wrapped in
|
|
1073
|
+
* [`React.startTransition`](https://react.dev/reference/react/startTransition).
|
|
1074
|
+
*
|
|
1075
|
+
* - When left `undefined`, all router state updates are wrapped in
|
|
1076
|
+
* `React.startTransition`
|
|
1077
|
+
* - When set to `true`, {@link Link} and {@link Form} navigations will be wrapped
|
|
1078
|
+
* in `React.startTransition` and all router state updates are wrapped in
|
|
1079
|
+
* `React.startTransition`
|
|
1080
|
+
* - When set to `false`, the router will not leverage `React.startTransition`
|
|
1081
|
+
* on any navigations or state changes.
|
|
1082
|
+
*
|
|
1083
|
+
* For more information, please see the [docs](https://reactrouter.com/explanation/react-transitions).
|
|
1084
|
+
*/
|
|
1085
|
+
unstable_useTransitions?: boolean;
|
|
1196
1086
|
}
|
|
1197
1087
|
/**
|
|
1198
1088
|
* A declarative {@link Router | `<Router>`} that accepts a pre-instantiated
|
|
@@ -1209,10 +1099,11 @@ interface HistoryRouterProps {
|
|
|
1209
1099
|
* @param {HistoryRouterProps.basename} props.basename n/a
|
|
1210
1100
|
* @param {HistoryRouterProps.children} props.children n/a
|
|
1211
1101
|
* @param {HistoryRouterProps.history} props.history n/a
|
|
1102
|
+
* @param {HistoryRouterProps.unstable_useTransitions} props.unstable_useTransitions n/a
|
|
1212
1103
|
* @returns A declarative {@link Router | `<Router>`} using the provided history
|
|
1213
1104
|
* implementation for client-side routing.
|
|
1214
1105
|
*/
|
|
1215
|
-
declare function HistoryRouter({ basename, children, history, }: HistoryRouterProps): React.JSX.Element;
|
|
1106
|
+
declare function HistoryRouter({ basename, children, history, unstable_useTransitions, }: HistoryRouterProps): React.JSX.Element;
|
|
1216
1107
|
declare namespace HistoryRouter {
|
|
1217
1108
|
var displayName: string;
|
|
1218
1109
|
}
|
|
@@ -1830,15 +1721,19 @@ declare namespace ScrollRestoration {
|
|
|
1830
1721
|
* @param options.viewTransition Enables a [View Transition](https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API)
|
|
1831
1722
|
* for this navigation. To apply specific styles during the transition, see
|
|
1832
1723
|
* {@link useViewTransitionState}. Defaults to `false`.
|
|
1724
|
+
* @param options.unstable_useTransitions Wraps the navigation in
|
|
1725
|
+
* [`React.startTransition`](https://react.dev/reference/react/startTransition)
|
|
1726
|
+
* for concurrent rendering. Defaults to `false`.
|
|
1833
1727
|
* @returns A click handler function that can be used in a custom {@link Link} component.
|
|
1834
1728
|
*/
|
|
1835
|
-
declare function useLinkClickHandler<E extends Element = HTMLAnchorElement>(to: To, { target, replace: replaceProp, state, preventScrollReset, relative, viewTransition, }?: {
|
|
1729
|
+
declare function useLinkClickHandler<E extends Element = HTMLAnchorElement>(to: To, { target, replace: replaceProp, state, preventScrollReset, relative, viewTransition, unstable_useTransitions, }?: {
|
|
1836
1730
|
target?: React.HTMLAttributeAnchorTarget;
|
|
1837
1731
|
replace?: boolean;
|
|
1838
1732
|
state?: any;
|
|
1839
1733
|
preventScrollReset?: boolean;
|
|
1840
1734
|
relative?: RelativeRoutingType;
|
|
1841
1735
|
viewTransition?: boolean;
|
|
1736
|
+
unstable_useTransitions?: boolean;
|
|
1842
1737
|
}): (event: React.MouseEvent<E, MouseEvent>) => void;
|
|
1843
1738
|
/**
|
|
1844
1739
|
* Returns a tuple of the current URL's [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams)
|
|
@@ -2167,7 +2062,7 @@ type FetcherWithComponents<TData> = Fetcher<TData> & {
|
|
|
2167
2062
|
* @param reason Optional `reason` to provide to [`AbortController.abort()`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController/abort)
|
|
2168
2063
|
* @returns void
|
|
2169
2064
|
*/
|
|
2170
|
-
|
|
2065
|
+
reset: (opts?: {
|
|
2171
2066
|
reason?: unknown;
|
|
2172
2067
|
}) => void;
|
|
2173
2068
|
/**
|
|
@@ -2256,7 +2151,7 @@ type FetcherWithComponents<TData> = Fetcher<TData> & {
|
|
|
2256
2151
|
* })
|
|
2257
2152
|
*
|
|
2258
2153
|
* // reset fetcher
|
|
2259
|
-
* fetcher.
|
|
2154
|
+
* fetcher.reset()
|
|
2260
2155
|
* }
|
|
2261
2156
|
*
|
|
2262
2157
|
* @public
|