UNPKG

6.99 kBJavaScriptView Raw
1/**
2 * react-router v8.4.0
3 *
4 * Copyright (c) Remix Software Inc.
5 *
6 * This source code is licensed under the MIT license found in the
7 * LICENSE.md file in the root directory of this source tree.
8 *
9 * @license MIT
10 */
11import { CRITICAL_CSS_DATA_ATTRIBUTE } from "../dom/ssr/components.js";
12import { RouterProvider as RouterProvider$1 } from "./dom-router-provider.js";
13import * as React$1 from "react";
14import { UNSAFE_FrameworkContext, UNSAFE_RemixErrorBoundary, UNSAFE_createBrowserHistory, UNSAFE_createClientRoutes, UNSAFE_createClientRoutesWithHMRRevalidationOptOut, UNSAFE_createRouter, UNSAFE_decodeViaTurboStream, UNSAFE_defaultMapRouteProperties, UNSAFE_getHydrationData, UNSAFE_getPatchRoutesOnNavigationFunction, UNSAFE_getTurboStreamSingleFetchDataStrategy, UNSAFE_hydrationRouteProperties, UNSAFE_invariant, UNSAFE_useFogOFWarDiscovery } from "react-router";
15//#region lib/dom-export/hydrated-router.tsx
16let ssrInfo = null;
17let router = null;
18function initSsrInfo() {
19 if (!ssrInfo && window.__reactRouterContext && window.__reactRouterManifest && window.__reactRouterRouteModules) {
20 if (window.__reactRouterManifest.sri === true) {
21 const importMap = document.querySelector("script[rr-importmap]");
22 if (importMap?.textContent) try {
23 window.__reactRouterManifest.sri = JSON.parse(importMap.textContent).integrity;
24 } catch (err) {
25 console.error("Failed to parse import map", err);
26 }
27 }
28 ssrInfo = {
29 context: window.__reactRouterContext,
30 manifest: window.__reactRouterManifest,
31 routeModules: window.__reactRouterRouteModules,
32 stateDecodingPromise: void 0,
33 router: void 0,
34 routerInitialized: false
35 };
36 }
37}
38function createHydratedRouter({ getContext, instrumentations }) {
39 initSsrInfo();
40 if (!ssrInfo) throw new Error("You must be using the SSR features of React Router in order to skip passing a `router` prop to `<RouterProvider>`");
41 let localSsrInfo = ssrInfo;
42 if (!ssrInfo.stateDecodingPromise) {
43 let stream = ssrInfo.context.stream;
44 UNSAFE_invariant(stream, "No stream found for single fetch decoding");
45 ssrInfo.context.stream = void 0;
46 ssrInfo.stateDecodingPromise = UNSAFE_decodeViaTurboStream(stream, window).then((value) => {
47 ssrInfo.context.state = value.value;
48 localSsrInfo.stateDecodingPromise.value = true;
49 }).catch((e) => {
50 localSsrInfo.stateDecodingPromise.error = e;
51 });
52 }
53 if (ssrInfo.stateDecodingPromise.error) throw ssrInfo.stateDecodingPromise.error;
54 if (!ssrInfo.stateDecodingPromise.value) throw ssrInfo.stateDecodingPromise;
55 let routes = UNSAFE_createClientRoutes(ssrInfo.manifest.routes, ssrInfo.routeModules, ssrInfo.context.state, ssrInfo.context.ssr, ssrInfo.context.isSpaMode);
56 let hydrationData = void 0;
57 if (ssrInfo.context.isSpaMode) {
58 let { loaderData } = ssrInfo.context.state;
59 if (ssrInfo.manifest.routes.root?.hasLoader && loaderData && "root" in loaderData) hydrationData = { loaderData: { root: loaderData.root } };
60 } else hydrationData = UNSAFE_getHydrationData({
61 state: ssrInfo.context.state,
62 routes,
63 getRouteInfo: (routeId) => ({
64 clientLoader: ssrInfo.routeModules[routeId]?.clientLoader,
65 hasLoader: ssrInfo.manifest.routes[routeId]?.hasLoader === true,
66 hasHydrateFallback: ssrInfo.routeModules[routeId]?.HydrateFallback != null
67 }),
68 location: window.location,
69 basename: window.__reactRouterContext?.basename,
70 future: ssrInfo.context.future,
71 isSpaMode: ssrInfo.context.isSpaMode
72 });
73 if (window.history.state && window.history.state.masked) window.history.replaceState({
74 ...window.history.state,
75 masked: void 0
76 }, "");
77 let router = UNSAFE_createRouter({
78 routes,
79 history: UNSAFE_createBrowserHistory(),
80 basename: ssrInfo.context.basename,
81 getContext,
82 hydrationData,
83 mapRouteProperties: UNSAFE_defaultMapRouteProperties,
84 hydrationRouteProperties: UNSAFE_hydrationRouteProperties,
85 instrumentations,
86 dataStrategy: UNSAFE_getTurboStreamSingleFetchDataStrategy(() => router, ssrInfo.manifest, ssrInfo.routeModules, ssrInfo.context.ssr),
87 patchRoutesOnNavigation: UNSAFE_getPatchRoutesOnNavigationFunction(() => router, ssrInfo.manifest, ssrInfo.routeModules, ssrInfo.context.ssr, ssrInfo.context.routeDiscovery, ssrInfo.context.isSpaMode, ssrInfo.context.basename)
88 });
89 ssrInfo.router = router;
90 if (router.state.initialized) {
91 ssrInfo.routerInitialized = true;
92 router.initialize();
93 }
94 router.createRoutesForHMR = UNSAFE_createClientRoutesWithHMRRevalidationOptOut;
95 window.__reactRouterDataRouter = router;
96 return router;
97}
98/**
99* Framework-mode router component to be used to hydrate a router from a
100* {@link ServerRouter}. See [`entry.client.tsx`](../framework-conventions/entry.client.tsx).
101*
102* @public
103* @category Framework Routers
104* @mode framework
105* @param props Props
106* @param {dom.HydratedRouterProps.getContext} props.getContext n/a
107* @param {dom.HydratedRouterProps.onError} props.onError n/a
108* @returns A React element that represents the hydrated application.
109*/
110function HydratedRouter(props) {
111 if (!router) router = createHydratedRouter({
112 getContext: props.getContext,
113 instrumentations: props.instrumentations
114 });
115 let [criticalCss, setCriticalCss] = React$1.useState(process.env.NODE_ENV === "development" ? ssrInfo?.context.criticalCss : void 0);
116 React$1.useEffect(() => {
117 if (process.env.NODE_ENV === "development") setCriticalCss(void 0);
118 }, []);
119 React$1.useEffect(() => {
120 if (process.env.NODE_ENV === "development" && criticalCss === void 0) document.querySelectorAll(`[${CRITICAL_CSS_DATA_ATTRIBUTE}]`).forEach((element) => element.remove());
121 }, [criticalCss]);
122 let [location, setLocation] = React$1.useState(router.state.location);
123 React$1.useLayoutEffect(() => {
124 if (ssrInfo && ssrInfo.router && !ssrInfo.routerInitialized) {
125 ssrInfo.routerInitialized = true;
126 ssrInfo.router.initialize();
127 }
128 }, []);
129 React$1.useLayoutEffect(() => {
130 if (ssrInfo && ssrInfo.router) return ssrInfo.router.subscribe((newState) => {
131 if (newState.location !== location) setLocation(newState.location);
132 });
133 }, [location]);
134 UNSAFE_invariant(ssrInfo, "ssrInfo unavailable for HydratedRouter");
135 UNSAFE_useFogOFWarDiscovery(router, ssrInfo.manifest, ssrInfo.routeModules, ssrInfo.context.ssr, ssrInfo.context.routeDiscovery, ssrInfo.context.isSpaMode);
136 return /* @__PURE__ */ React$1.createElement(React$1.Fragment, null, /* @__PURE__ */ React$1.createElement(UNSAFE_FrameworkContext.Provider, { value: {
137 manifest: ssrInfo.manifest,
138 routeModules: ssrInfo.routeModules,
139 future: ssrInfo.context.future,
140 criticalCss,
141 ssr: ssrInfo.context.ssr,
142 isSpaMode: ssrInfo.context.isSpaMode,
143 routeDiscovery: ssrInfo.context.routeDiscovery
144 } }, /* @__PURE__ */ React$1.createElement(UNSAFE_RemixErrorBoundary, { location }, /* @__PURE__ */ React$1.createElement(RouterProvider$1, {
145 router,
146 useTransitions: props.useTransitions,
147 onError: props.onError
148 }))), /* @__PURE__ */ React$1.createElement(React$1.Fragment, null));
149}
150//#endregion
151export { HydratedRouter };