UNPKG

48.7 kBJavaScriptView Raw
1/**
2 * React Router v6.19.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 * as React from 'react';
12import { UNSAFE_invariant, joinPaths, matchPath, UNSAFE_getPathContributingMatches, UNSAFE_warning, resolveTo, parsePath, matchRoutes, Action, UNSAFE_convertRouteMatchToUiMatch, stripBasename, IDLE_BLOCKER, isRouteErrorResponse, createMemoryHistory, AbortedDeferredError, createRouter } from '@remix-run/router';
13export { AbortedDeferredError, Action as NavigationType, createPath, defer, generatePath, isRouteErrorResponse, json, matchPath, matchRoutes, parsePath, redirect, redirectDocument, resolvePath } from '@remix-run/router';
14
15const DataRouterContext = /*#__PURE__*/React.createContext(null);
16{
17 DataRouterContext.displayName = "DataRouter";
18}
19const DataRouterStateContext = /*#__PURE__*/React.createContext(null);
20{
21 DataRouterStateContext.displayName = "DataRouterState";
22}
23const AwaitContext = /*#__PURE__*/React.createContext(null);
24{
25 AwaitContext.displayName = "Await";
26}
27const NavigationContext = /*#__PURE__*/React.createContext(null);
28{
29 NavigationContext.displayName = "Navigation";
30}
31const LocationContext = /*#__PURE__*/React.createContext(null);
32{
33 LocationContext.displayName = "Location";
34}
35const RouteContext = /*#__PURE__*/React.createContext({
36 outlet: null,
37 matches: [],
38 isDataRoute: false
39});
40{
41 RouteContext.displayName = "Route";
42}
43const RouteErrorContext = /*#__PURE__*/React.createContext(null);
44{
45 RouteErrorContext.displayName = "RouteError";
46}
47
48/**
49 * Returns the full href for the given "to" value. This is useful for building
50 * custom links that are also accessible and preserve right-click behavior.
51 *
52 * @see https://reactrouter.com/hooks/use-href
53 */
54function useHref(to, {
55 relative
56} = {}) {
57 !useInRouterContext() ? UNSAFE_invariant(false,
58 // TODO: This error is probably because they somehow have 2 versions of the
59 // router loaded. We can help them understand how to avoid that.
60 `useHref() may be used only in the context of a <Router> component.`) : void 0;
61 let {
62 basename,
63 navigator
64 } = React.useContext(NavigationContext);
65 let {
66 hash,
67 pathname,
68 search
69 } = useResolvedPath(to, {
70 relative
71 });
72 let joinedPathname = pathname;
73 // If we're operating within a basename, prepend it to the pathname prior
74 // to creating the href. If this is a root navigation, then just use the raw
75 // basename which allows the basename to have full control over the presence
76 // of a trailing slash on root links
77 if (basename !== "/") {
78 joinedPathname = pathname === "/" ? basename : joinPaths([basename, pathname]);
79 }
80 return navigator.createHref({
81 pathname: joinedPathname,
82 search,
83 hash
84 });
85}
86/**
87 * Returns true if this component is a descendant of a `<Router>`.
88 *
89 * @see https://reactrouter.com/hooks/use-in-router-context
90 */
91function useInRouterContext() {
92 return React.useContext(LocationContext) != null;
93}
94/**
95 * Returns the current location object, which represents the current URL in web
96 * browsers.
97 *
98 * Note: If you're using this it may mean you're doing some of your own
99 * "routing" in your app, and we'd like to know what your use case is. We may
100 * be able to provide something higher-level to better suit your needs.
101 *
102 * @see https://reactrouter.com/hooks/use-location
103 */
104function useLocation() {
105 !useInRouterContext() ? UNSAFE_invariant(false,
106 // TODO: This error is probably because they somehow have 2 versions of the
107 // router loaded. We can help them understand how to avoid that.
108 `useLocation() may be used only in the context of a <Router> component.`) : void 0;
109 return React.useContext(LocationContext).location;
110}
111/**
112 * Returns the current navigation action which describes how the router came to
113 * the current location, either by a pop, push, or replace on the history stack.
114 *
115 * @see https://reactrouter.com/hooks/use-navigation-type
116 */
117function useNavigationType() {
118 return React.useContext(LocationContext).navigationType;
119}
120/**
121 * Returns a PathMatch object if the given pattern matches the current URL.
122 * This is useful for components that need to know "active" state, e.g.
123 * `<NavLink>`.
124 *
125 * @see https://reactrouter.com/hooks/use-match
126 */
127function useMatch(pattern) {
128 !useInRouterContext() ? UNSAFE_invariant(false,
129 // TODO: This error is probably because they somehow have 2 versions of the
130 // router loaded. We can help them understand how to avoid that.
131 `useMatch() may be used only in the context of a <Router> component.`) : void 0;
132 let {
133 pathname
134 } = useLocation();
135 return React.useMemo(() => matchPath(pattern, pathname), [pathname, pattern]);
136}
137const navigateEffectWarning = `You should call navigate() in a React.useEffect(), not when ` + `your component is first rendered.`;
138// Mute warnings for calls to useNavigate in SSR environments
139function useIsomorphicLayoutEffect(cb) {
140 let isStatic = React.useContext(NavigationContext).static;
141 if (!isStatic) {
142 // We should be able to get rid of this once react 18.3 is released
143 // See: https://github.com/facebook/react/pull/26395
144 // eslint-disable-next-line react-hooks/rules-of-hooks
145 React.useLayoutEffect(cb);
146 }
147}
148/**
149 * Returns an imperative method for changing the location. Used by `<Link>`s, but
150 * may also be used by other elements to change the location.
151 *
152 * @see https://reactrouter.com/hooks/use-navigate
153 */
154function useNavigate() {
155 let {
156 isDataRoute
157 } = React.useContext(RouteContext);
158 // Conditional usage is OK here because the usage of a data router is static
159 // eslint-disable-next-line react-hooks/rules-of-hooks
160 return isDataRoute ? useNavigateStable() : useNavigateUnstable();
161}
162function useNavigateUnstable() {
163 !useInRouterContext() ? UNSAFE_invariant(false,
164 // TODO: This error is probably because they somehow have 2 versions of the
165 // router loaded. We can help them understand how to avoid that.
166 `useNavigate() may be used only in the context of a <Router> component.`) : void 0;
167 let dataRouterContext = React.useContext(DataRouterContext);
168 let {
169 basename,
170 navigator
171 } = React.useContext(NavigationContext);
172 let {
173 matches
174 } = React.useContext(RouteContext);
175 let {
176 pathname: locationPathname
177 } = useLocation();
178 let routePathnamesJson = JSON.stringify(UNSAFE_getPathContributingMatches(matches).map(match => match.pathnameBase));
179 let activeRef = React.useRef(false);
180 useIsomorphicLayoutEffect(() => {
181 activeRef.current = true;
182 });
183 let navigate = React.useCallback((to, options = {}) => {
184 UNSAFE_warning(activeRef.current, navigateEffectWarning) ;
185 // Short circuit here since if this happens on first render the navigate
186 // is useless because we haven't wired up our history listener yet
187 if (!activeRef.current) return;
188 if (typeof to === "number") {
189 navigator.go(to);
190 return;
191 }
192 let path = resolveTo(to, JSON.parse(routePathnamesJson), locationPathname, options.relative === "path");
193 // If we're operating within a basename, prepend it to the pathname prior
194 // to handing off to history (but only if we're not in a data router,
195 // otherwise it'll prepend the basename inside of the router).
196 // If this is a root navigation, then we navigate to the raw basename
197 // which allows the basename to have full control over the presence of a
198 // trailing slash on root links
199 if (dataRouterContext == null && basename !== "/") {
200 path.pathname = path.pathname === "/" ? basename : joinPaths([basename, path.pathname]);
201 }
202 (!!options.replace ? navigator.replace : navigator.push)(path, options.state, options);
203 }, [basename, navigator, routePathnamesJson, locationPathname, dataRouterContext]);
204 return navigate;
205}
206const OutletContext = /*#__PURE__*/React.createContext(null);
207/**
208 * Returns the context (if provided) for the child route at this level of the route
209 * hierarchy.
210 * @see https://reactrouter.com/hooks/use-outlet-context
211 */
212function useOutletContext() {
213 return React.useContext(OutletContext);
214}
215/**
216 * Returns the element for the child route at this level of the route
217 * hierarchy. Used internally by `<Outlet>` to render child routes.
218 *
219 * @see https://reactrouter.com/hooks/use-outlet
220 */
221function useOutlet(context) {
222 let outlet = React.useContext(RouteContext).outlet;
223 if (outlet) {
224 return /*#__PURE__*/React.createElement(OutletContext.Provider, {
225 value: context
226 }, outlet);
227 }
228 return outlet;
229}
230/**
231 * Returns an object of key/value pairs of the dynamic params from the current
232 * URL that were matched by the route path.
233 *
234 * @see https://reactrouter.com/hooks/use-params
235 */
236function useParams() {
237 let {
238 matches
239 } = React.useContext(RouteContext);
240 let routeMatch = matches[matches.length - 1];
241 return routeMatch ? routeMatch.params : {};
242}
243/**
244 * Resolves the pathname of the given `to` value against the current location.
245 *
246 * @see https://reactrouter.com/hooks/use-resolved-path
247 */
248function useResolvedPath(to, {
249 relative
250} = {}) {
251 let {
252 matches
253 } = React.useContext(RouteContext);
254 let {
255 pathname: locationPathname
256 } = useLocation();
257 // Use the full pathname for the leaf match so we include splat values
258 // for "." links
259 let routePathnamesJson = JSON.stringify(UNSAFE_getPathContributingMatches(matches).map((match, idx) => idx === matches.length - 1 ? match.pathname : match.pathnameBase));
260 return React.useMemo(() => resolveTo(to, JSON.parse(routePathnamesJson), locationPathname, relative === "path"), [to, routePathnamesJson, locationPathname, relative]);
261}
262/**
263 * Returns the element of the route that matched the current location, prepared
264 * with the correct context to render the remainder of the route tree. Route
265 * elements in the tree must render an `<Outlet>` to render their child route's
266 * element.
267 *
268 * @see https://reactrouter.com/hooks/use-routes
269 */
270function useRoutes(routes, locationArg) {
271 return useRoutesImpl(routes, locationArg);
272}
273// Internal implementation with accept optional param for RouterProvider usage
274function useRoutesImpl(routes, locationArg, dataRouterState) {
275 !useInRouterContext() ? UNSAFE_invariant(false,
276 // TODO: This error is probably because they somehow have 2 versions of the
277 // router loaded. We can help them understand how to avoid that.
278 `useRoutes() may be used only in the context of a <Router> component.`) : void 0;
279 let {
280 navigator
281 } = React.useContext(NavigationContext);
282 let {
283 matches: parentMatches
284 } = React.useContext(RouteContext);
285 let routeMatch = parentMatches[parentMatches.length - 1];
286 let parentParams = routeMatch ? routeMatch.params : {};
287 let parentPathname = routeMatch ? routeMatch.pathname : "/";
288 let parentPathnameBase = routeMatch ? routeMatch.pathnameBase : "/";
289 let parentRoute = routeMatch && routeMatch.route;
290 {
291 // You won't get a warning about 2 different <Routes> under a <Route>
292 // without a trailing *, but this is a best-effort warning anyway since we
293 // cannot even give the warning unless they land at the parent route.
294 //
295 // Example:
296 //
297 // <Routes>
298 // {/* This route path MUST end with /* because otherwise
299 // it will never match /blog/post/123 */}
300 // <Route path="blog" element={<Blog />} />
301 // <Route path="blog/feed" element={<BlogFeed />} />
302 // </Routes>
303 //
304 // function Blog() {
305 // return (
306 // <Routes>
307 // <Route path="post/:id" element={<Post />} />
308 // </Routes>
309 // );
310 // }
311 let parentPath = parentRoute && parentRoute.path || "";
312 warningOnce(parentPathname, !parentRoute || parentPath.endsWith("*"), `You rendered descendant <Routes> (or called \`useRoutes()\`) at ` + `"${parentPathname}" (under <Route path="${parentPath}">) but the ` + `parent route path has no trailing "*". This means if you navigate ` + `deeper, the parent won't match anymore and therefore the child ` + `routes will never render.\n\n` + `Please change the parent <Route path="${parentPath}"> to <Route ` + `path="${parentPath === "/" ? "*" : `${parentPath}/*`}">.`);
313 }
314 let locationFromContext = useLocation();
315 let location;
316 if (locationArg) {
317 let parsedLocationArg = typeof locationArg === "string" ? parsePath(locationArg) : locationArg;
318 !(parentPathnameBase === "/" || parsedLocationArg.pathname?.startsWith(parentPathnameBase)) ? UNSAFE_invariant(false, `When overriding the location using \`<Routes location>\` or \`useRoutes(routes, location)\`, ` + `the location pathname must begin with the portion of the URL pathname that was ` + `matched by all parent routes. The current pathname base is "${parentPathnameBase}" ` + `but pathname "${parsedLocationArg.pathname}" was given in the \`location\` prop.`) : void 0;
319 location = parsedLocationArg;
320 } else {
321 location = locationFromContext;
322 }
323 let pathname = location.pathname || "/";
324 let remainingPathname = parentPathnameBase === "/" ? pathname : pathname.slice(parentPathnameBase.length) || "/";
325 let matches = matchRoutes(routes, {
326 pathname: remainingPathname
327 });
328 {
329 UNSAFE_warning(parentRoute || matches != null, `No routes matched location "${location.pathname}${location.search}${location.hash}" `) ;
330 UNSAFE_warning(matches == null || matches[matches.length - 1].route.element !== undefined || matches[matches.length - 1].route.Component !== undefined, `Matched leaf route at location "${location.pathname}${location.search}${location.hash}" ` + `does not have an element or Component. This means it will render an <Outlet /> with a ` + `null value by default resulting in an "empty" page.`) ;
331 }
332 let renderedMatches = _renderMatches(matches && matches.map(match => Object.assign({}, match, {
333 params: Object.assign({}, parentParams, match.params),
334 pathname: joinPaths([parentPathnameBase,
335 // Re-encode pathnames that were decoded inside matchRoutes
336 navigator.encodeLocation ? navigator.encodeLocation(match.pathname).pathname : match.pathname]),
337 pathnameBase: match.pathnameBase === "/" ? parentPathnameBase : joinPaths([parentPathnameBase,
338 // Re-encode pathnames that were decoded inside matchRoutes
339 navigator.encodeLocation ? navigator.encodeLocation(match.pathnameBase).pathname : match.pathnameBase])
340 })), parentMatches, dataRouterState);
341 // When a user passes in a `locationArg`, the associated routes need to
342 // be wrapped in a new `LocationContext.Provider` in order for `useLocation`
343 // to use the scoped location instead of the global location.
344 if (locationArg && renderedMatches) {
345 return /*#__PURE__*/React.createElement(LocationContext.Provider, {
346 value: {
347 location: {
348 pathname: "/",
349 search: "",
350 hash: "",
351 state: null,
352 key: "default",
353 ...location
354 },
355 navigationType: Action.Pop
356 }
357 }, renderedMatches);
358 }
359 return renderedMatches;
360}
361function DefaultErrorComponent() {
362 let error = useRouteError();
363 let message = isRouteErrorResponse(error) ? `${error.status} ${error.statusText}` : error instanceof Error ? error.message : JSON.stringify(error);
364 let stack = error instanceof Error ? error.stack : null;
365 let lightgrey = "rgba(200,200,200, 0.5)";
366 let preStyles = {
367 padding: "0.5rem",
368 backgroundColor: lightgrey
369 };
370 let codeStyles = {
371 padding: "2px 4px",
372 backgroundColor: lightgrey
373 };
374 let devInfo = null;
375 {
376 console.error("Error handled by React Router default ErrorBoundary:", error);
377 devInfo = /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("p", null, "\uD83D\uDCBF Hey developer \uD83D\uDC4B"), /*#__PURE__*/React.createElement("p", null, "You can provide a way better UX than this when your app throws errors by providing your own ", /*#__PURE__*/React.createElement("code", {
378 style: codeStyles
379 }, "ErrorBoundary"), " or", " ", /*#__PURE__*/React.createElement("code", {
380 style: codeStyles
381 }, "errorElement"), " prop on your route."));
382 }
383 return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("h2", null, "Unexpected Application Error!"), /*#__PURE__*/React.createElement("h3", {
384 style: {
385 fontStyle: "italic"
386 }
387 }, message), stack ? /*#__PURE__*/React.createElement("pre", {
388 style: preStyles
389 }, stack) : null, devInfo);
390}
391const defaultErrorElement = /*#__PURE__*/React.createElement(DefaultErrorComponent, null);
392class RenderErrorBoundary extends React.Component {
393 constructor(props) {
394 super(props);
395 this.state = {
396 location: props.location,
397 revalidation: props.revalidation,
398 error: props.error
399 };
400 }
401 static getDerivedStateFromError(error) {
402 return {
403 error: error
404 };
405 }
406 static getDerivedStateFromProps(props, state) {
407 // When we get into an error state, the user will likely click "back" to the
408 // previous page that didn't have an error. Because this wraps the entire
409 // application, that will have no effect--the error page continues to display.
410 // This gives us a mechanism to recover from the error when the location changes.
411 //
412 // Whether we're in an error state or not, we update the location in state
413 // so that when we are in an error state, it gets reset when a new location
414 // comes in and the user recovers from the error.
415 if (state.location !== props.location || state.revalidation !== "idle" && props.revalidation === "idle") {
416 return {
417 error: props.error,
418 location: props.location,
419 revalidation: props.revalidation
420 };
421 }
422 // If we're not changing locations, preserve the location but still surface
423 // any new errors that may come through. We retain the existing error, we do
424 // this because the error provided from the app state may be cleared without
425 // the location changing.
426 return {
427 error: props.error || state.error,
428 location: state.location,
429 revalidation: props.revalidation || state.revalidation
430 };
431 }
432 componentDidCatch(error, errorInfo) {
433 console.error("React Router caught the following error during render", error, errorInfo);
434 }
435 render() {
436 return this.state.error ? /*#__PURE__*/React.createElement(RouteContext.Provider, {
437 value: this.props.routeContext
438 }, /*#__PURE__*/React.createElement(RouteErrorContext.Provider, {
439 value: this.state.error,
440 children: this.props.component
441 })) : this.props.children;
442 }
443}
444function RenderedRoute({
445 routeContext,
446 match,
447 children
448}) {
449 let dataRouterContext = React.useContext(DataRouterContext);
450 // Track how deep we got in our render pass to emulate SSR componentDidCatch
451 // in a DataStaticRouter
452 if (dataRouterContext && dataRouterContext.static && dataRouterContext.staticContext && (match.route.errorElement || match.route.ErrorBoundary)) {
453 dataRouterContext.staticContext._deepestRenderedBoundaryId = match.route.id;
454 }
455 return /*#__PURE__*/React.createElement(RouteContext.Provider, {
456 value: routeContext
457 }, children);
458}
459function _renderMatches(matches, parentMatches = [], dataRouterState = null) {
460 if (matches == null) {
461 if (dataRouterState?.errors) {
462 // Don't bail if we have data router errors so we can render them in the
463 // boundary. Use the pre-matched (or shimmed) matches
464 matches = dataRouterState.matches;
465 } else {
466 return null;
467 }
468 }
469 let renderedMatches = matches;
470 // If we have data errors, trim matches to the highest error boundary
471 let errors = dataRouterState?.errors;
472 if (errors != null) {
473 let errorIndex = renderedMatches.findIndex(m => m.route.id && errors?.[m.route.id]);
474 !(errorIndex >= 0) ? UNSAFE_invariant(false, `Could not find a matching route for errors on route IDs: ${Object.keys(errors).join(",")}`) : void 0;
475 renderedMatches = renderedMatches.slice(0, Math.min(renderedMatches.length, errorIndex + 1));
476 }
477 return renderedMatches.reduceRight((outlet, match, index) => {
478 let error = match.route.id ? errors?.[match.route.id] : null;
479 // Only data routers handle errors
480 let errorElement = null;
481 if (dataRouterState) {
482 errorElement = match.route.errorElement || defaultErrorElement;
483 }
484 let matches = parentMatches.concat(renderedMatches.slice(0, index + 1));
485 let getChildren = () => {
486 let children;
487 if (error) {
488 children = errorElement;
489 } else if (match.route.Component) {
490 // Note: This is a de-optimized path since React won't re-use the
491 // ReactElement since it's identity changes with each new
492 // React.createElement call. We keep this so folks can use
493 // `<Route Component={...}>` in `<Routes>` but generally `Component`
494 // usage is only advised in `RouterProvider` when we can convert it to
495 // `element` ahead of time.
496 children = /*#__PURE__*/React.createElement(match.route.Component, null);
497 } else if (match.route.element) {
498 children = match.route.element;
499 } else {
500 children = outlet;
501 }
502 return /*#__PURE__*/React.createElement(RenderedRoute, {
503 match: match,
504 routeContext: {
505 outlet,
506 matches,
507 isDataRoute: dataRouterState != null
508 },
509 children: children
510 });
511 };
512 // Only wrap in an error boundary within data router usages when we have an
513 // ErrorBoundary/errorElement on this route. Otherwise let it bubble up to
514 // an ancestor ErrorBoundary/errorElement
515 return dataRouterState && (match.route.ErrorBoundary || match.route.errorElement || index === 0) ? /*#__PURE__*/React.createElement(RenderErrorBoundary, {
516 location: dataRouterState.location,
517 revalidation: dataRouterState.revalidation,
518 component: errorElement,
519 error: error,
520 children: getChildren(),
521 routeContext: {
522 outlet: null,
523 matches,
524 isDataRoute: true
525 }
526 }) : getChildren();
527 }, null);
528}
529var DataRouterHook;
530(function (DataRouterHook) {
531 DataRouterHook["UseBlocker"] = "useBlocker";
532 DataRouterHook["UseRevalidator"] = "useRevalidator";
533 DataRouterHook["UseNavigateStable"] = "useNavigate";
534})(DataRouterHook || (DataRouterHook = {}));
535var DataRouterStateHook;
536(function (DataRouterStateHook) {
537 DataRouterStateHook["UseBlocker"] = "useBlocker";
538 DataRouterStateHook["UseLoaderData"] = "useLoaderData";
539 DataRouterStateHook["UseActionData"] = "useActionData";
540 DataRouterStateHook["UseRouteError"] = "useRouteError";
541 DataRouterStateHook["UseNavigation"] = "useNavigation";
542 DataRouterStateHook["UseRouteLoaderData"] = "useRouteLoaderData";
543 DataRouterStateHook["UseMatches"] = "useMatches";
544 DataRouterStateHook["UseRevalidator"] = "useRevalidator";
545 DataRouterStateHook["UseNavigateStable"] = "useNavigate";
546 DataRouterStateHook["UseRouteId"] = "useRouteId";
547})(DataRouterStateHook || (DataRouterStateHook = {}));
548function getDataRouterConsoleError(hookName) {
549 return `${hookName} must be used within a data router. See https://reactrouter.com/routers/picking-a-router.`;
550}
551function useDataRouterContext(hookName) {
552 let ctx = React.useContext(DataRouterContext);
553 !ctx ? UNSAFE_invariant(false, getDataRouterConsoleError(hookName)) : void 0;
554 return ctx;
555}
556function useDataRouterState(hookName) {
557 let state = React.useContext(DataRouterStateContext);
558 !state ? UNSAFE_invariant(false, getDataRouterConsoleError(hookName)) : void 0;
559 return state;
560}
561function useRouteContext(hookName) {
562 let route = React.useContext(RouteContext);
563 !route ? UNSAFE_invariant(false, getDataRouterConsoleError(hookName)) : void 0;
564 return route;
565}
566// Internal version with hookName-aware debugging
567function useCurrentRouteId(hookName) {
568 let route = useRouteContext(hookName);
569 let thisRoute = route.matches[route.matches.length - 1];
570 !thisRoute.route.id ? UNSAFE_invariant(false, `${hookName} can only be used on routes that contain a unique "id"`) : void 0;
571 return thisRoute.route.id;
572}
573/**
574 * Returns the ID for the nearest contextual route
575 */
576function useRouteId() {
577 return useCurrentRouteId(DataRouterStateHook.UseRouteId);
578}
579/**
580 * Returns the current navigation, defaulting to an "idle" navigation when
581 * no navigation is in progress
582 */
583function useNavigation() {
584 let state = useDataRouterState(DataRouterStateHook.UseNavigation);
585 return state.navigation;
586}
587/**
588 * Returns a revalidate function for manually triggering revalidation, as well
589 * as the current state of any manual revalidations
590 */
591function useRevalidator() {
592 let dataRouterContext = useDataRouterContext(DataRouterHook.UseRevalidator);
593 let state = useDataRouterState(DataRouterStateHook.UseRevalidator);
594 return React.useMemo(() => ({
595 revalidate: dataRouterContext.router.revalidate,
596 state: state.revalidation
597 }), [dataRouterContext.router.revalidate, state.revalidation]);
598}
599/**
600 * Returns the active route matches, useful for accessing loaderData for
601 * parent/child routes or the route "handle" property
602 */
603function useMatches() {
604 let {
605 matches,
606 loaderData
607 } = useDataRouterState(DataRouterStateHook.UseMatches);
608 return React.useMemo(() => matches.map(m => UNSAFE_convertRouteMatchToUiMatch(m, loaderData)), [matches, loaderData]);
609}
610/**
611 * Returns the loader data for the nearest ancestor Route loader
612 */
613function useLoaderData() {
614 let state = useDataRouterState(DataRouterStateHook.UseLoaderData);
615 let routeId = useCurrentRouteId(DataRouterStateHook.UseLoaderData);
616 if (state.errors && state.errors[routeId] != null) {
617 console.error(`You cannot \`useLoaderData\` in an errorElement (routeId: ${routeId})`);
618 return undefined;
619 }
620 return state.loaderData[routeId];
621}
622/**
623 * Returns the loaderData for the given routeId
624 */
625function useRouteLoaderData(routeId) {
626 let state = useDataRouterState(DataRouterStateHook.UseRouteLoaderData);
627 return state.loaderData[routeId];
628}
629/**
630 * Returns the action data for the nearest ancestor Route action
631 */
632function useActionData() {
633 let state = useDataRouterState(DataRouterStateHook.UseActionData);
634 let routeId = useCurrentRouteId(DataRouterStateHook.UseLoaderData);
635 return state.actionData ? state.actionData[routeId] : undefined;
636}
637/**
638 * Returns the nearest ancestor Route error, which could be a loader/action
639 * error or a render error. This is intended to be called from your
640 * ErrorBoundary/errorElement to display a proper error message.
641 */
642function useRouteError() {
643 let error = React.useContext(RouteErrorContext);
644 let state = useDataRouterState(DataRouterStateHook.UseRouteError);
645 let routeId = useCurrentRouteId(DataRouterStateHook.UseRouteError);
646 // If this was a render error, we put it in a RouteError context inside
647 // of RenderErrorBoundary
648 if (error) {
649 return error;
650 }
651 // Otherwise look for errors from our data router state
652 return state.errors?.[routeId];
653}
654/**
655 * Returns the happy-path data from the nearest ancestor `<Await />` value
656 */
657function useAsyncValue() {
658 let value = React.useContext(AwaitContext);
659 return value?._data;
660}
661/**
662 * Returns the error from the nearest ancestor `<Await />` value
663 */
664function useAsyncError() {
665 let value = React.useContext(AwaitContext);
666 return value?._error;
667}
668let blockerId = 0;
669/**
670 * Allow the application to block navigations within the SPA and present the
671 * user a confirmation dialog to confirm the navigation. Mostly used to avoid
672 * using half-filled form data. This does not handle hard-reloads or
673 * cross-origin navigations.
674 */
675function useBlocker(shouldBlock) {
676 let {
677 router,
678 basename
679 } = useDataRouterContext(DataRouterHook.UseBlocker);
680 let state = useDataRouterState(DataRouterStateHook.UseBlocker);
681 let [blockerKey, setBlockerKey] = React.useState("");
682 let blockerFunction = React.useCallback(arg => {
683 if (typeof shouldBlock !== "function") {
684 return !!shouldBlock;
685 }
686 if (basename === "/") {
687 return shouldBlock(arg);
688 }
689 // If they provided us a function and we've got an active basename, strip
690 // it from the locations we expose to the user to match the behavior of
691 // useLocation
692 let {
693 currentLocation,
694 nextLocation,
695 historyAction
696 } = arg;
697 return shouldBlock({
698 currentLocation: {
699 ...currentLocation,
700 pathname: stripBasename(currentLocation.pathname, basename) || currentLocation.pathname
701 },
702 nextLocation: {
703 ...nextLocation,
704 pathname: stripBasename(nextLocation.pathname, basename) || nextLocation.pathname
705 },
706 historyAction
707 });
708 }, [basename, shouldBlock]);
709 // This effect is in charge of blocker key assignment and deletion (which is
710 // tightly coupled to the key)
711 React.useEffect(() => {
712 let key = String(++blockerId);
713 setBlockerKey(key);
714 return () => router.deleteBlocker(key);
715 }, [router]);
716 // This effect handles assigning the blockerFunction. This is to handle
717 // unstable blocker function identities, and happens only after the prior
718 // effect so we don't get an orphaned blockerFunction in the router with a
719 // key of "". Until then we just have the IDLE_BLOCKER.
720 React.useEffect(() => {
721 if (blockerKey !== "") {
722 router.getBlocker(blockerKey, blockerFunction);
723 }
724 }, [router, blockerKey, blockerFunction]);
725 // Prefer the blocker from `state` not `router.state` since DataRouterContext
726 // is memoized so this ensures we update on blocker state updates
727 return blockerKey && state.blockers.has(blockerKey) ? state.blockers.get(blockerKey) : IDLE_BLOCKER;
728}
729/**
730 * Stable version of useNavigate that is used when we are in the context of
731 * a RouterProvider.
732 */
733function useNavigateStable() {
734 let {
735 router
736 } = useDataRouterContext(DataRouterHook.UseNavigateStable);
737 let id = useCurrentRouteId(DataRouterStateHook.UseNavigateStable);
738 let activeRef = React.useRef(false);
739 useIsomorphicLayoutEffect(() => {
740 activeRef.current = true;
741 });
742 let navigate = React.useCallback((to, options = {}) => {
743 UNSAFE_warning(activeRef.current, navigateEffectWarning) ;
744 // Short circuit here since if this happens on first render the navigate
745 // is useless because we haven't wired up our router subscriber yet
746 if (!activeRef.current) return;
747 if (typeof to === "number") {
748 router.navigate(to);
749 } else {
750 router.navigate(to, {
751 fromRouteId: id,
752 ...options
753 });
754 }
755 }, [router, id]);
756 return navigate;
757}
758const alreadyWarned = {};
759function warningOnce(key, cond, message) {
760 if (!cond && !alreadyWarned[key]) {
761 alreadyWarned[key] = true;
762 UNSAFE_warning(false, message) ;
763 }
764}
765
766/**
767 Webpack + React 17 fails to compile on any of the following because webpack
768 complains that `startTransition` doesn't exist in `React`:
769 * import { startTransition } from "react"
770 * import * as React from from "react";
771 "startTransition" in React ? React.startTransition(() => setState()) : setState()
772 * import * as React from from "react";
773 "startTransition" in React ? React["startTransition"](() => setState()) : setState()
774
775 Moving it to a constant such as the following solves the Webpack/React 17 issue:
776 * import * as React from from "react";
777 const START_TRANSITION = "startTransition";
778 START_TRANSITION in React ? React[START_TRANSITION](() => setState()) : setState()
779
780 However, that introduces webpack/terser minification issues in production builds
781 in React 18 where minification/obfuscation ends up removing the call of
782 React.startTransition entirely from the first half of the ternary. Grabbing
783 this exported reference once up front resolves that issue.
784
785 See https://github.com/remix-run/react-router/issues/10579
786*/
787const START_TRANSITION = "startTransition";
788const startTransitionImpl = React[START_TRANSITION];
789/**
790 * Given a Remix Router instance, render the appropriate UI
791 */
792function RouterProvider({
793 fallbackElement,
794 router,
795 future
796}) {
797 let [state, setStateImpl] = React.useState(router.state);
798 let {
799 v7_startTransition
800 } = future || {};
801 let setState = React.useCallback(newState => {
802 if (v7_startTransition && startTransitionImpl) {
803 startTransitionImpl(() => setStateImpl(newState));
804 } else {
805 setStateImpl(newState);
806 }
807 }, [setStateImpl, v7_startTransition]);
808 // Need to use a layout effect here so we are subscribed early enough to
809 // pick up on any render-driven redirects/navigations (useEffect/<Navigate>)
810 React.useLayoutEffect(() => router.subscribe(setState), [router, setState]);
811 let navigator = React.useMemo(() => {
812 return {
813 createHref: router.createHref,
814 encodeLocation: router.encodeLocation,
815 go: n => router.navigate(n),
816 push: (to, state, opts) => router.navigate(to, {
817 state,
818 preventScrollReset: opts?.preventScrollReset
819 }),
820 replace: (to, state, opts) => router.navigate(to, {
821 replace: true,
822 state,
823 preventScrollReset: opts?.preventScrollReset
824 })
825 };
826 }, [router]);
827 let basename = router.basename || "/";
828 let dataRouterContext = React.useMemo(() => ({
829 router,
830 navigator,
831 static: false,
832 basename
833 }), [router, navigator, basename]);
834 // The fragment and {null} here are important! We need them to keep React 18's
835 // useId happy when we are server-rendering since we may have a <script> here
836 // containing the hydrated server-side staticContext (from StaticRouterProvider).
837 // useId relies on the component tree structure to generate deterministic id's
838 // so we need to ensure it remains the same on the client even though
839 // we don't need the <script> tag
840 return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(DataRouterContext.Provider, {
841 value: dataRouterContext
842 }, /*#__PURE__*/React.createElement(DataRouterStateContext.Provider, {
843 value: state
844 }, /*#__PURE__*/React.createElement(Router, {
845 basename: basename,
846 location: state.location,
847 navigationType: state.historyAction,
848 navigator: navigator
849 }, state.initialized ? /*#__PURE__*/React.createElement(DataRoutes, {
850 routes: router.routes,
851 state: state
852 }) : fallbackElement))), null);
853}
854function DataRoutes({
855 routes,
856 state
857}) {
858 return useRoutesImpl(routes, undefined, state);
859}
860/**
861 * A `<Router>` that stores all entries in memory.
862 *
863 * @see https://reactrouter.com/router-components/memory-router
864 */
865function MemoryRouter({
866 basename,
867 children,
868 initialEntries,
869 initialIndex,
870 future
871}) {
872 let historyRef = React.useRef();
873 if (historyRef.current == null) {
874 historyRef.current = createMemoryHistory({
875 initialEntries,
876 initialIndex,
877 v5Compat: true
878 });
879 }
880 let history = historyRef.current;
881 let [state, setStateImpl] = React.useState({
882 action: history.action,
883 location: history.location
884 });
885 let {
886 v7_startTransition
887 } = future || {};
888 let setState = React.useCallback(newState => {
889 v7_startTransition && startTransitionImpl ? startTransitionImpl(() => setStateImpl(newState)) : setStateImpl(newState);
890 }, [setStateImpl, v7_startTransition]);
891 React.useLayoutEffect(() => history.listen(setState), [history, setState]);
892 return /*#__PURE__*/React.createElement(Router, {
893 basename: basename,
894 children: children,
895 location: state.location,
896 navigationType: state.action,
897 navigator: history
898 });
899}
900/**
901 * Changes the current location.
902 *
903 * Note: This API is mostly useful in React.Component subclasses that are not
904 * able to use hooks. In functional components, we recommend you use the
905 * `useNavigate` hook instead.
906 *
907 * @see https://reactrouter.com/components/navigate
908 */
909function Navigate({
910 to,
911 replace,
912 state,
913 relative
914}) {
915 !useInRouterContext() ? UNSAFE_invariant(false,
916 // TODO: This error is probably because they somehow have 2 versions of
917 // the router loaded. We can help them understand how to avoid that.
918 `<Navigate> may be used only in the context of a <Router> component.`) : void 0;
919 UNSAFE_warning(!React.useContext(NavigationContext).static, `<Navigate> must not be used on the initial render in a <StaticRouter>. ` + `This is a no-op, but you should modify your code so the <Navigate> is ` + `only ever rendered in response to some user interaction or state change.`) ;
920 let {
921 matches
922 } = React.useContext(RouteContext);
923 let {
924 pathname: locationPathname
925 } = useLocation();
926 let navigate = useNavigate();
927 // Resolve the path outside of the effect so that when effects run twice in
928 // StrictMode they navigate to the same place
929 let path = resolveTo(to, UNSAFE_getPathContributingMatches(matches).map(match => match.pathnameBase), locationPathname, relative === "path");
930 let jsonPath = JSON.stringify(path);
931 React.useEffect(() => navigate(JSON.parse(jsonPath), {
932 replace,
933 state,
934 relative
935 }), [navigate, jsonPath, relative, replace, state]);
936 return null;
937}
938/**
939 * Renders the child route's element, if there is one.
940 *
941 * @see https://reactrouter.com/components/outlet
942 */
943function Outlet(props) {
944 return useOutlet(props.context);
945}
946/**
947 * Declares an element that should be rendered at a certain URL path.
948 *
949 * @see https://reactrouter.com/components/route
950 */
951function Route(_props) {
952 UNSAFE_invariant(false, `A <Route> is only ever to be used as the child of <Routes> element, ` + `never rendered directly. Please wrap your <Route> in a <Routes>.`) ;
953}
954/**
955 * Provides location context for the rest of the app.
956 *
957 * Note: You usually won't render a `<Router>` directly. Instead, you'll render a
958 * router that is more specific to your environment such as a `<BrowserRouter>`
959 * in web browsers or a `<StaticRouter>` for server rendering.
960 *
961 * @see https://reactrouter.com/router-components/router
962 */
963function Router({
964 basename: basenameProp = "/",
965 children = null,
966 location: locationProp,
967 navigationType = Action.Pop,
968 navigator,
969 static: staticProp = false
970}) {
971 !!useInRouterContext() ? UNSAFE_invariant(false, `You cannot render a <Router> inside another <Router>.` + ` You should never have more than one in your app.`) : void 0;
972 // Preserve trailing slashes on basename, so we can let the user control
973 // the enforcement of trailing slashes throughout the app
974 let basename = basenameProp.replace(/^\/*/, "/");
975 let navigationContext = React.useMemo(() => ({
976 basename,
977 navigator,
978 static: staticProp
979 }), [basename, navigator, staticProp]);
980 if (typeof locationProp === "string") {
981 locationProp = parsePath(locationProp);
982 }
983 let {
984 pathname = "/",
985 search = "",
986 hash = "",
987 state = null,
988 key = "default"
989 } = locationProp;
990 let locationContext = React.useMemo(() => {
991 let trailingPathname = stripBasename(pathname, basename);
992 if (trailingPathname == null) {
993 return null;
994 }
995 return {
996 location: {
997 pathname: trailingPathname,
998 search,
999 hash,
1000 state,
1001 key
1002 },
1003 navigationType
1004 };
1005 }, [basename, pathname, search, hash, state, key, navigationType]);
1006 UNSAFE_warning(locationContext != null, `<Router basename="${basename}"> is not able to match the URL ` + `"${pathname}${search}${hash}" because it does not start with the ` + `basename, so the <Router> won't render anything.`) ;
1007 if (locationContext == null) {
1008 return null;
1009 }
1010 return /*#__PURE__*/React.createElement(NavigationContext.Provider, {
1011 value: navigationContext
1012 }, /*#__PURE__*/React.createElement(LocationContext.Provider, {
1013 children: children,
1014 value: locationContext
1015 }));
1016}
1017/**
1018 * A container for a nested tree of `<Route>` elements that renders the branch
1019 * that best matches the current location.
1020 *
1021 * @see https://reactrouter.com/components/routes
1022 */
1023function Routes({
1024 children,
1025 location
1026}) {
1027 return useRoutes(createRoutesFromChildren(children), location);
1028}
1029/**
1030 * Component to use for rendering lazily loaded data from returning defer()
1031 * in a loader function
1032 */
1033function Await({
1034 children,
1035 errorElement,
1036 resolve
1037}) {
1038 return /*#__PURE__*/React.createElement(AwaitErrorBoundary, {
1039 resolve: resolve,
1040 errorElement: errorElement
1041 }, /*#__PURE__*/React.createElement(ResolveAwait, null, children));
1042}
1043var AwaitRenderStatus;
1044(function (AwaitRenderStatus) {
1045 AwaitRenderStatus[AwaitRenderStatus["pending"] = 0] = "pending";
1046 AwaitRenderStatus[AwaitRenderStatus["success"] = 1] = "success";
1047 AwaitRenderStatus[AwaitRenderStatus["error"] = 2] = "error";
1048})(AwaitRenderStatus || (AwaitRenderStatus = {}));
1049const neverSettledPromise = new Promise(() => {});
1050class AwaitErrorBoundary extends React.Component {
1051 constructor(props) {
1052 super(props);
1053 this.state = {
1054 error: null
1055 };
1056 }
1057 static getDerivedStateFromError(error) {
1058 return {
1059 error
1060 };
1061 }
1062 componentDidCatch(error, errorInfo) {
1063 console.error("<Await> caught the following error during render", error, errorInfo);
1064 }
1065 render() {
1066 let {
1067 children,
1068 errorElement,
1069 resolve
1070 } = this.props;
1071 let promise = null;
1072 let status = AwaitRenderStatus.pending;
1073 if (!(resolve instanceof Promise)) {
1074 // Didn't get a promise - provide as a resolved promise
1075 status = AwaitRenderStatus.success;
1076 promise = Promise.resolve();
1077 Object.defineProperty(promise, "_tracked", {
1078 get: () => true
1079 });
1080 Object.defineProperty(promise, "_data", {
1081 get: () => resolve
1082 });
1083 } else if (this.state.error) {
1084 // Caught a render error, provide it as a rejected promise
1085 status = AwaitRenderStatus.error;
1086 let renderError = this.state.error;
1087 promise = Promise.reject().catch(() => {}); // Avoid unhandled rejection warnings
1088 Object.defineProperty(promise, "_tracked", {
1089 get: () => true
1090 });
1091 Object.defineProperty(promise, "_error", {
1092 get: () => renderError
1093 });
1094 } else if (resolve._tracked) {
1095 // Already tracked promise - check contents
1096 promise = resolve;
1097 status = promise._error !== undefined ? AwaitRenderStatus.error : promise._data !== undefined ? AwaitRenderStatus.success : AwaitRenderStatus.pending;
1098 } else {
1099 // Raw (untracked) promise - track it
1100 status = AwaitRenderStatus.pending;
1101 Object.defineProperty(resolve, "_tracked", {
1102 get: () => true
1103 });
1104 promise = resolve.then(data => Object.defineProperty(resolve, "_data", {
1105 get: () => data
1106 }), error => Object.defineProperty(resolve, "_error", {
1107 get: () => error
1108 }));
1109 }
1110 if (status === AwaitRenderStatus.error && promise._error instanceof AbortedDeferredError) {
1111 // Freeze the UI by throwing a never resolved promise
1112 throw neverSettledPromise;
1113 }
1114 if (status === AwaitRenderStatus.error && !errorElement) {
1115 // No errorElement, throw to the nearest route-level error boundary
1116 throw promise._error;
1117 }
1118 if (status === AwaitRenderStatus.error) {
1119 // Render via our errorElement
1120 return /*#__PURE__*/React.createElement(AwaitContext.Provider, {
1121 value: promise,
1122 children: errorElement
1123 });
1124 }
1125 if (status === AwaitRenderStatus.success) {
1126 // Render children with resolved value
1127 return /*#__PURE__*/React.createElement(AwaitContext.Provider, {
1128 value: promise,
1129 children: children
1130 });
1131 }
1132 // Throw to the suspense boundary
1133 throw promise;
1134 }
1135}
1136/**
1137 * @private
1138 * Indirection to leverage useAsyncValue for a render-prop API on `<Await>`
1139 */
1140function ResolveAwait({
1141 children
1142}) {
1143 let data = useAsyncValue();
1144 let toRender = typeof children === "function" ? children(data) : children;
1145 return /*#__PURE__*/React.createElement(React.Fragment, null, toRender);
1146}
1147///////////////////////////////////////////////////////////////////////////////
1148// UTILS
1149///////////////////////////////////////////////////////////////////////////////
1150/**
1151 * Creates a route config from a React "children" object, which is usually
1152 * either a `<Route>` element or an array of them. Used internally by
1153 * `<Routes>` to create a route config from its children.
1154 *
1155 * @see https://reactrouter.com/utils/create-routes-from-children
1156 */
1157function createRoutesFromChildren(children, parentPath = []) {
1158 let routes = [];
1159 React.Children.forEach(children, (element, index) => {
1160 if (! /*#__PURE__*/React.isValidElement(element)) {
1161 // Ignore non-elements. This allows people to more easily inline
1162 // conditionals in their route config.
1163 return;
1164 }
1165 let treePath = [...parentPath, index];
1166 if (element.type === React.Fragment) {
1167 // Transparently support React.Fragment and its children.
1168 routes.push.apply(routes, createRoutesFromChildren(element.props.children, treePath));
1169 return;
1170 }
1171 !(element.type === Route) ? UNSAFE_invariant(false, `[${typeof element.type === "string" ? element.type : element.type.name}] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment>`) : void 0;
1172 !(!element.props.index || !element.props.children) ? UNSAFE_invariant(false, "An index route cannot have child routes.") : void 0;
1173 let route = {
1174 id: element.props.id || treePath.join("-"),
1175 caseSensitive: element.props.caseSensitive,
1176 element: element.props.element,
1177 Component: element.props.Component,
1178 index: element.props.index,
1179 path: element.props.path,
1180 loader: element.props.loader,
1181 action: element.props.action,
1182 errorElement: element.props.errorElement,
1183 ErrorBoundary: element.props.ErrorBoundary,
1184 hasErrorBoundary: element.props.ErrorBoundary != null || element.props.errorElement != null,
1185 shouldRevalidate: element.props.shouldRevalidate,
1186 handle: element.props.handle,
1187 lazy: element.props.lazy
1188 };
1189 if (element.props.children) {
1190 route.children = createRoutesFromChildren(element.props.children, treePath);
1191 }
1192 routes.push(route);
1193 });
1194 return routes;
1195}
1196/**
1197 * Renders the result of `matchRoutes()` into a React element.
1198 */
1199function renderMatches(matches) {
1200 return _renderMatches(matches);
1201}
1202
1203function mapRouteProperties(route) {
1204 let updates = {
1205 // Note: this check also occurs in createRoutesFromChildren so update
1206 // there if you change this -- please and thank you!
1207 hasErrorBoundary: route.ErrorBoundary != null || route.errorElement != null
1208 };
1209 if (route.Component) {
1210 {
1211 if (route.element) {
1212 UNSAFE_warning(false, "You should not include both `Component` and `element` on your route - " + "`Component` will be used.") ;
1213 }
1214 }
1215 Object.assign(updates, {
1216 element: /*#__PURE__*/React.createElement(route.Component),
1217 Component: undefined
1218 });
1219 }
1220 if (route.ErrorBoundary) {
1221 {
1222 if (route.errorElement) {
1223 UNSAFE_warning(false, "You should not include both `ErrorBoundary` and `errorElement` on your route - " + "`ErrorBoundary` will be used.") ;
1224 }
1225 }
1226 Object.assign(updates, {
1227 errorElement: /*#__PURE__*/React.createElement(route.ErrorBoundary),
1228 ErrorBoundary: undefined
1229 });
1230 }
1231 return updates;
1232}
1233function createMemoryRouter(routes, opts) {
1234 return createRouter({
1235 basename: opts?.basename,
1236 future: {
1237 ...opts?.future,
1238 v7_prependBasename: true
1239 },
1240 history: createMemoryHistory({
1241 initialEntries: opts?.initialEntries,
1242 initialIndex: opts?.initialIndex
1243 }),
1244 hydrationData: opts?.hydrationData,
1245 routes,
1246 mapRouteProperties
1247 }).initialize();
1248}
1249
1250export { Await, MemoryRouter, Navigate, Outlet, Route, Router, RouterProvider, Routes, DataRouterContext as UNSAFE_DataRouterContext, DataRouterStateContext as UNSAFE_DataRouterStateContext, LocationContext as UNSAFE_LocationContext, NavigationContext as UNSAFE_NavigationContext, RouteContext as UNSAFE_RouteContext, mapRouteProperties as UNSAFE_mapRouteProperties, useRouteId as UNSAFE_useRouteId, useRoutesImpl as UNSAFE_useRoutesImpl, createMemoryRouter, createRoutesFromChildren, createRoutesFromChildren as createRoutesFromElements, renderMatches, useActionData, useAsyncError, useAsyncValue, useBlocker, useHref, useInRouterContext, useLoaderData, useLocation, useMatch, useMatches, useNavigate, useNavigation, useNavigationType, useOutlet, useOutletContext, useParams, useResolvedPath, useRevalidator, useRouteError, useRouteLoaderData, useRoutes };
1251//# sourceMappingURL=react-router.development.js.map