UNPKG

6.95 kBJavaScriptView Raw
1/**
2 * react-router v8.0.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 isSpaMode: ssrInfo.context.isSpaMode
71 });
72 if (window.history.state && window.history.state.masked) window.history.replaceState({
73 ...window.history.state,
74 masked: void 0
75 }, "");
76 let router = UNSAFE_createRouter({
77 routes,
78 history: UNSAFE_createBrowserHistory(),
79 basename: ssrInfo.context.basename,
80 getContext,
81 hydrationData,
82 mapRouteProperties: UNSAFE_defaultMapRouteProperties,
83 hydrationRouteProperties: UNSAFE_hydrationRouteProperties,
84 instrumentations,
85 dataStrategy: UNSAFE_getTurboStreamSingleFetchDataStrategy(() => router, ssrInfo.manifest, ssrInfo.routeModules, ssrInfo.context.ssr),
86 patchRoutesOnNavigation: UNSAFE_getPatchRoutesOnNavigationFunction(() => router, ssrInfo.manifest, ssrInfo.routeModules, ssrInfo.context.ssr, ssrInfo.context.routeDiscovery, ssrInfo.context.isSpaMode, ssrInfo.context.basename)
87 });
88 ssrInfo.router = router;
89 if (router.state.initialized) {
90 ssrInfo.routerInitialized = true;
91 router.initialize();
92 }
93 router.createRoutesForHMR = UNSAFE_createClientRoutesWithHMRRevalidationOptOut;
94 window.__reactRouterDataRouter = router;
95 return router;
96}
97/**
98* Framework-mode router component to be used to hydrate a router from a
99* {@link ServerRouter}. See [`entry.client.tsx`](../framework-conventions/entry.client.tsx).
100*
101* @public
102* @category Framework Routers
103* @mode framework
104* @param props Props
105* @param {dom.HydratedRouterProps.getContext} props.getContext n/a
106* @param {dom.HydratedRouterProps.onError} props.onError n/a
107* @returns A React element that represents the hydrated application.
108*/
109function HydratedRouter(props) {
110 if (!router) router = createHydratedRouter({
111 getContext: props.getContext,
112 instrumentations: props.instrumentations
113 });
114 let [criticalCss, setCriticalCss] = React$1.useState(process.env.NODE_ENV === "development" ? ssrInfo?.context.criticalCss : void 0);
115 React$1.useEffect(() => {
116 if (process.env.NODE_ENV === "development") setCriticalCss(void 0);
117 }, []);
118 React$1.useEffect(() => {
119 if (process.env.NODE_ENV === "development" && criticalCss === void 0) document.querySelectorAll(`[${CRITICAL_CSS_DATA_ATTRIBUTE}]`).forEach((element) => element.remove());
120 }, [criticalCss]);
121 let [location, setLocation] = React$1.useState(router.state.location);
122 React$1.useLayoutEffect(() => {
123 if (ssrInfo && ssrInfo.router && !ssrInfo.routerInitialized) {
124 ssrInfo.routerInitialized = true;
125 ssrInfo.router.initialize();
126 }
127 }, []);
128 React$1.useLayoutEffect(() => {
129 if (ssrInfo && ssrInfo.router) return ssrInfo.router.subscribe((newState) => {
130 if (newState.location !== location) setLocation(newState.location);
131 });
132 }, [location]);
133 UNSAFE_invariant(ssrInfo, "ssrInfo unavailable for HydratedRouter");
134 UNSAFE_useFogOFWarDiscovery(router, ssrInfo.manifest, ssrInfo.routeModules, ssrInfo.context.ssr, ssrInfo.context.routeDiscovery, ssrInfo.context.isSpaMode);
135 return /* @__PURE__ */ React$1.createElement(React$1.Fragment, null, /* @__PURE__ */ React$1.createElement(UNSAFE_FrameworkContext.Provider, { value: {
136 manifest: ssrInfo.manifest,
137 routeModules: ssrInfo.routeModules,
138 future: ssrInfo.context.future,
139 criticalCss,
140 ssr: ssrInfo.context.ssr,
141 isSpaMode: ssrInfo.context.isSpaMode,
142 routeDiscovery: ssrInfo.context.routeDiscovery
143 } }, /* @__PURE__ */ React$1.createElement(UNSAFE_RemixErrorBoundary, { location }, /* @__PURE__ */ React$1.createElement(RouterProvider$1, {
144 router,
145 useTransitions: props.useTransitions,
146 onError: props.onError
147 }))), /* @__PURE__ */ React$1.createElement(React$1.Fragment, null));
148}
149//#endregion
150export { HydratedRouter };