react-router
Version:
Declarative routing for React
1,322 lines (1,305 loc) • 56.9 kB
text/typescript
import { R as Router, y as RouteModules, D as DataStrategyFunction, T as To, z as NavigateOptions, B as BlockerFunction, E as Blocker, J as SerializeFrom, a as RelativeRoutingType, c as Location, K as ParamParseKey, O as Path, Q as PathPattern, V as PathMatch, U as UIMatch, W as Navigation, A as Action, h as Params, f as RouteObject, I as InitialEntry, H as HydrationState, b as IndexRouteObject, m as LoaderFunction, i as ActionFunction, M as MetaFunction, l as LinksFunction, N as NonIndexRouteObject, X as AppLoadContext, u as unstable_RouterContextProvider, Y as MiddlewareEnabled, Z as unstable_InitialContext, _ as Equal, e as RouterInit, $ as RouterState, P as PatchRoutesOnNavigationFunction, a0 as DataRouteObject, j as ClientLoaderFunction } from './route-data-CqEmXQub.mjs';
export { ab as ActionFunctionArgs, C as ClientActionFunction, aH as ClientActionFunctionArgs, aI as ClientLoaderFunctionArgs, aF as DataRouteMatch, ac as DataStrategyFunctionArgs, ad as DataStrategyMatch, ae as DataStrategyResult, ag as ErrorResponse, a5 as Fetcher, ah as FormEncType, ai as FormMethod, aN as Future, a2 as GetScrollPositionFunction, a3 as GetScrollRestorationKeyFunction, aj as HTMLFormMethod, aJ as HeadersArgs, k as HeadersFunction, aM as HtmlLinkDescriptor, av as IDLE_BLOCKER, au as IDLE_FETCHER, at as IDLE_NAVIGATION, L as LazyRouteFunction, o as LinkDescriptor, ak as LoaderFunctionArgs, aK as MetaArgs, q as MetaDescriptor, a6 as NavigationStates, d as Navigator, aL as PageLinkDescriptor, aG as PatchRoutesOnNavigationFunctionArgs, am as PathParam, an as RedirectFunction, aa as RevalidationState, g as RouteMatch, a9 as RouterFetchOptions, a8 as RouterNavigateOptions, a7 as RouterSubscriber, S as ShouldRevalidateFunction, ap as ShouldRevalidateFunctionArgs, a1 as StaticHandler, a4 as StaticHandlerContext, aT as UNSAFE_DataRouterContext, aU as UNSAFE_DataRouterStateContext, af as UNSAFE_DataWithResponseInit, aS as UNSAFE_ErrorResponseImpl, aV as UNSAFE_FetchersContext, aW as UNSAFE_LocationContext, aX as UNSAFE_NavigationContext, aY as UNSAFE_RouteContext, aZ as UNSAFE_ViewTransitionContext, aP as UNSAFE_createBrowserHistory, aR as UNSAFE_createRouter, aQ as UNSAFE_invariant, ar as createPath, aw as data, ax as generatePath, ay as isRouteErrorResponse, az as matchPath, aA as matchRoutes, as as parsePath, aB as redirect, aC as redirectDocument, aD as replace, aE as resolvePath, al as unstable_MiddlewareFunction, ao as unstable_RouterContext, aO as unstable_SerializesTo, aq as unstable_createContext } from './route-data-CqEmXQub.mjs';
import { a as RouteComponentType, H as HydrateFallbackType, E as ErrorBoundaryType } from './components-CjQijYga.mjs';
export { f as Await, A as AwaitProps, I as IndexRouteProps, L as LayoutRouteProps, g as MemoryRouter, M as MemoryRouterOpts, b as MemoryRouterProps, h as Navigate, N as NavigateProps, i as Outlet, O as OutletProps, P as PathRouteProps, j as Route, c as RouteProps, k as Router, d as RouterProps, l as RouterProvider, R as RouterProviderProps, m as Routes, e as RoutesProps, W as UNSAFE_WithComponentProps, v as UNSAFE_WithErrorBoundaryProps, t as UNSAFE_WithHydrateFallbackProps, q as UNSAFE_hydrationRouteProperties, s as UNSAFE_mapRouteProperties, w as UNSAFE_withComponentProps, x as UNSAFE_withErrorBoundaryProps, u as UNSAFE_withHydrateFallbackProps, n as createMemoryRouter, o as createRoutesFromChildren, p as createRoutesFromElements, r as renderMatches } from './components-CjQijYga.mjs';
import * as React from 'react';
import React__default, { ReactElement } from 'react';
import { A as AssetsManifest, E as EntryContext, F as FutureConfig, S as ServerBuild } from './index-react-server-client-KLg-U4nr.mjs';
export { l as BrowserRouter, B as BrowserRouterProps, D as DOMRouterOpts, a0 as DiscoverBehavior, c as FetcherFormProps, h as FetcherSubmitFunction, G as FetcherSubmitOptions, i as FetcherWithComponents, q as Form, d as FormProps, a1 as HandleDataRequestFunction, a2 as HandleDocumentRequestFunction, a3 as HandleErrorFunction, m as HashRouter, H as HashRouterProps, a as HistoryRouterProps, n as Link, L as LinkProps, X as Links, W as Meta, p as NavLink, N as NavLinkProps, b as NavLinkRenderProps, P as ParamKeyValuePair, $ as PrefetchBehavior, Z as PrefetchPageLinks, Y as Scripts, _ as ScriptsProps, r as ScrollRestoration, e as ScrollRestorationProps, a4 as ServerEntryModule, f as SetURLSearchParams, T as StaticRouter, M as StaticRouterProps, V as StaticRouterProvider, O as StaticRouterProviderProps, g as SubmitFunction, I as SubmitOptions, J as SubmitTarget, a5 as UNSAFE_FrameworkContext, a6 as UNSAFE_createClientRoutes, a7 as UNSAFE_createClientRoutesWithHMRRevalidationOptOut, a8 as UNSAFE_shouldHydrateRouteLoader, a9 as UNSAFE_useScrollRestoration, U as URLSearchParamsInit, j as createBrowserRouter, k as createHashRouter, K as createSearchParams, Q as createStaticHandler, R as createStaticRouter, o as unstable_HistoryRouter, z as unstable_usePrompt, y as useBeforeUnload, w as useFetcher, x as useFetchers, v as useFormAction, u as useLinkClickHandler, s as useSearchParams, t as useSubmit, C as useViewTransitionState } from './index-react-server-client-KLg-U4nr.mjs';
import { ParseOptions, SerializeOptions } from 'cookie';
export { ParseOptions as CookieParseOptions, SerializeOptions as CookieSerializeOptions } from 'cookie';
import { P as Pages } from './register-DiOIlEq5.mjs';
export { a as Register } from './register-DiOIlEq5.mjs';
import { R as RSCPayload, m as matchRSCServerRequest } from './browser-7LYX59NK.mjs';
export { D as unstable_DecodeActionFunction, a as unstable_DecodeFormStateFunction, b as unstable_DecodeReplyFunction, L as unstable_LoadServerActionFunction, c as unstable_RSCManifestPayload, d as unstable_RSCMatch, e as unstable_RSCRenderPayload, j as unstable_RSCRouteConfig, i as unstable_RSCRouteConfigEntry, f as unstable_RSCRouteManifest, h as unstable_RSCRouteMatch, g as unstable_getRSCStream } from './browser-7LYX59NK.mjs';
import 'node:async_hooks';
declare const SingleFetchRedirectSymbol: unique symbol;
declare function getTurboStreamSingleFetchDataStrategy(getRouter: () => Router, manifest: AssetsManifest, routeModules: RouteModules, ssr: boolean, basename: string | undefined): DataStrategyFunction;
declare function decodeViaTurboStream(body: ReadableStream<Uint8Array>, global: Window | typeof globalThis): Promise<{
done: Promise<undefined>;
value: unknown;
}>;
/**
* The mode to use when running the server.
*/
declare enum ServerMode {
Development = "development",
Production = "production",
Test = "test"
}
/**
* Resolves a URL against the current {@link Location}.
*
* @example
* import { useHref } from "react-router";
*
* function SomeComponent() {
* let href = useHref("some/where");
* // "/resolved/some/where"
* }
*
* @public
* @category Hooks
* @param to The path to resolve
* @param options Options
* @param options.relative Defaults to `"route"` so routing is relative to the
* route tree.
* Set to `"path"` to make relative routing operate against path segments.
* @returns The resolved href string
*/
declare function useHref(to: To, { relative }?: {
relative?: RelativeRoutingType;
}): string;
/**
* Returns `true` if this component is a descendant of a {@link Router}, useful
* to ensure a component is used within a {@link Router}.
*
* @public
* @category Hooks
* @mode framework
* @mode data
* @returns Whether the component is within a {@link Router} context
*/
declare function useInRouterContext(): boolean;
/**
* Returns the current {@link Location}. This can be useful if you'd like to
* perform some side effect whenever it changes.
*
* @example
* import * as React from 'react'
* import { useLocation } from 'react-router'
*
* function SomeComponent() {
* let location = useLocation()
*
* React.useEffect(() => {
* // Google Analytics
* ga('send', 'pageview')
* }, [location]);
*
* return (
* // ...
* );
* }
*
* @public
* @category Hooks
* @returns The current {@link Location} object
*/
declare function useLocation(): Location;
/**
* Returns the current {@link Navigation} action which describes how the router
* came to the current {@link Location}, either by a pop, push, or replace on
* the [`History`](https://developer.mozilla.org/en-US/docs/Web/API/History) stack.
*
* @public
* @category Hooks
* @returns The current {@link NavigationType} type (`"PUSH"`, `"REPLACE"`, or `"POP"`)
*/
declare function useNavigationType(): Action;
/**
* Returns a {@link PathMatch} object if the given pattern matches the current URL.
* This is useful for components that need to know "active" state, e.g.
* {@link NavLink | `<NavLink>`}.
*
* @public
* @category Hooks
* @param pattern The pattern to match against the current {@link Location}
* @returns The path match object if the pattern matches, `null` otherwise
*/
declare function useMatch<ParamKey extends ParamParseKey<Path>, Path extends string>(pattern: PathPattern<Path> | Path): PathMatch<ParamKey> | null;
/**
* The interface for the `navigate` function returned from {@link useNavigate}.
*/
interface NavigateFunction {
(to: To, options?: NavigateOptions): void | Promise<void>;
(delta: number): void | Promise<void>;
}
/**
* Returns a function that lets you navigate programmatically in the browser in
* response to user interactions or effects.
*
* It's often better to use {@link redirect} in [`action`](../../start/framework/route-module#action)/[`loader`](../../start/framework/route-module#loader)
* functions than this hook.
*
* The returned function signature is `navigate(to, options?)`/`navigate(delta)` where:
*
* * `to` can be a string path, a {@link To} object, or a number (delta)
* * `options` contains options for modifying the navigation
* * `flushSync`: Wrap the DOM updates in [`ReactDom.flushSync`](https://react.dev/reference/react-dom/flushSync)
* * `preventScrollReset`: Do not scroll back to the top of the page after navigation
* * `relative`: `"route"` or `"path"` to control relative routing logic
* * `replace`: Replace the current entry in the [`History`](https://developer.mozilla.org/en-US/docs/Web/API/History) stack
* * `state`: Optional [`history.state`](https://developer.mozilla.org/en-US/docs/Web/API/History/state) to include with the new {@link Location}
* * `viewTransition`: Enable [`document.startViewTransition`](https://developer.mozilla.org/en-US/docs/Web/API/Document/startViewTransition) for this navigation
*
* @example
* import { useNavigate } from "react-router";
*
* function SomeComponent() {
* let navigate = useNavigate();
* return (
* <button onClick={() => navigate(-1)}>
* Go Back
* </button>
* );
* }
*
* @additionalExamples
* ### Navigate to another path
*
* ```tsx
* navigate("/some/route");
* navigate("/some/route?search=param");
* ```
*
* ### Navigate with a {@link To} object
*
* All properties are optional.
*
* ```tsx
* navigate({
* pathname: "/some/route",
* search: "?search=param",
* hash: "#hash",
* state: { some: "state" },
* });
* ```
*
* If you use `state`, that will be available on the {@link Location} object on
* the next page. Access it with `useLocation().state` (see {@link useLocation}).
*
* ### Navigate back or forward in the history stack
*
* ```tsx
* // back
* // often used to close modals
* navigate(-1);
*
* // forward
* // often used in a multistep wizard workflows
* navigate(1);
* ```
*
* Be cautious with `navigate(number)`. If your application can load up to a
* route that has a button that tries to navigate forward/back, there may not be
* a `[`History`](https://developer.mozilla.org/en-US/docs/Web/API/History)
* entry to go back or forward to, or it can go somewhere you don't expect
* (like a different domain).
*
* Only use this if you're sure they will have an entry in the [`History`](https://developer.mozilla.org/en-US/docs/Web/API/History)
* stack to navigate to.
*
* ### Replace the current entry in the history stack
*
* This will remove the current entry in the [`History`](https://developer.mozilla.org/en-US/docs/Web/API/History)
* stack, replacing it with a new one, similar to a server side redirect.
*
* ```tsx
* navigate("/some/route", { replace: true });
* ```
*
* ### Prevent Scroll Reset
*
* [MODES: framework, data]
*
* <br/>
* <br/>
*
* To prevent {@link ScrollRestoration | `<ScrollRestoration>`} from resetting
* the scroll position, use the `preventScrollReset` option.
*
* ```tsx
* navigate("?some-tab=1", { preventScrollReset: true });
* ```
*
* For example, if you have a tab interface connected to search params in the
* middle of a page, and you don't want it to scroll to the top when a tab is
* clicked.
*
* @public
* @category Hooks
* @returns A navigate function for programmatic navigation
*/
declare function useNavigate(): NavigateFunction;
/**
* Returns the parent route {@link Outlet | `<Outlet context>`}.
*
* Often parent routes manage state or other values you want shared with child
* routes. You can create your own [context provider](https://react.dev/learn/passing-data-deeply-with-context)
* if you like, but this is such a common situation that it's built-into
* `<Outlet />`.
*
* ```tsx
* // Parent route
* function Parent() {
* const [count, setCount] = React.useState(0);
* return <Outlet context={[count, setCount]} />;
* }
* ```
*
* ```tsx
* // Child route
* import { useOutletContext } from "react-router-dom";
*
* function Child() {
* const [count, setCount] = useOutletContext();
* const increment = () => setCount((c) => c + 1);
* return <button onClick={increment}>{count}</button>;
* }
* ```
*
* If you're using TypeScript, we recommend the parent component provide a custom
* hook for accessing the context value. This makes it easier for consumers to
* get nice typings, control consumers, and know who's consuming the context value.
*
* Here's a more realistic example:
*
* ```tsx filename=src/routes/dashboard.tsx lines=[13,19]
* import * as React from "react";
* import type { User } from "./types";
* import { Outlet, useOutletContext } from "react-router-dom";
*
* type ContextType = { user: User | null };
*
* export default function Dashboard() {
* const [user, setUser] = React.useState<User | null>(null);
*
* return (
* <div>
* <h1>Dashboard</h1>
* <Outlet context={{ user } satisfies ContextType} />
* </div>
* );
* }
*
* export function useUser() {
* return useOutletContext<ContextType>();
* }
* ```
*
* ```tsx filename=src/routes/dashboard/messages.tsx lines=[1,4]
* import { useUser } from "../dashboard";
*
* export default function DashboardMessages() {
* const { user } = useUser();
* return (
* <div>
* <h2>Messages</h2>
* <p>Hello, {user.name}!</p>
* </div>
* );
* }
* ```
*
* @public
* @category Hooks
* @returns The context value passed to the parent {@link Outlet} component
*/
declare function useOutletContext<Context = unknown>(): Context;
/**
* Returns the element for the child route at this level of the route
* hierarchy. Used internally by {@link Outlet | `<Outlet>`} to render child
* routes.
*
* @public
* @category Hooks
* @param context The context to pass to the outlet
* @returns The child route element or `null` if no child routes match
*/
declare function useOutlet(context?: unknown): React.ReactElement | null;
/**
* Returns an object of key/value-pairs of the dynamic params from the current
* URL that were matched by the routes. Child routes inherit all params from
* their parent routes.
*
* Assuming a route pattern like `/posts/:postId` is matched by `/posts/123`
* then `params.postId` will be `"123"`.
*
* @example
* import { useParams } from "react-router";
*
* function SomeComponent() {
* let params = useParams();
* params.postId;
* }
*
* @additionalExamples
* ### Basic Usage
*
* ```tsx
* import { useParams } from "react-router";
*
* // given a route like:
* <Route path="/posts/:postId" element={<Post />} />;
*
* // or a data route like:
* createBrowserRouter([
* {
* path: "/posts/:postId",
* component: Post,
* },
* ]);
*
* // or in routes.ts
* route("/posts/:postId", "routes/post.tsx");
* ```
*
* Access the params in a component:
*
* ```tsx
* import { useParams } from "react-router";
*
* export default function Post() {
* let params = useParams();
* return <h1>Post: {params.postId}</h1>;
* }
* ```
*
* ### Multiple Params
*
* Patterns can have multiple params:
*
* ```tsx
* "/posts/:postId/comments/:commentId";
* ```
*
* All will be available in the params object:
*
* ```tsx
* import { useParams } from "react-router";
*
* export default function Post() {
* let params = useParams();
* return (
* <h1>
* Post: {params.postId}, Comment: {params.commentId}
* </h1>
* );
* }
* ```
*
* ### Catchall Params
*
* Catchall params are defined with `*`:
*
* ```tsx
* "/files/*";
* ```
*
* The matched value will be available in the params object as follows:
*
* ```tsx
* import { useParams } from "react-router";
*
* export default function File() {
* let params = useParams();
* let catchall = params["*"];
* // ...
* }
* ```
*
* You can destructure the catchall param:
*
* ```tsx
* export default function File() {
* let { "*": catchall } = useParams();
* console.log(catchall);
* }
* ```
*
* @public
* @category Hooks
* @returns An object containing the dynamic route parameters
*/
declare function useParams<ParamsOrKey extends string | Record<string, string | undefined> = string>(): Readonly<[
ParamsOrKey
] extends [string] ? Params<ParamsOrKey> : Partial<ParamsOrKey>>;
/**
* Resolves the pathname of the given `to` value against the current
* {@link Location}. Similar to {@link useHref}, but returns a
* {@link Path} instead of a string.
*
* @example
* import { useResolvedPath } from "react-router";
*
* function SomeComponent() {
* // if the user is at /dashboard/profile
* let path = useResolvedPath("../accounts");
* path.pathname; // "/dashboard/accounts"
* path.search; // ""
* path.hash; // ""
* }
*
* @public
* @category Hooks
* @param to The path to resolve
* @param options Options
* @param options.relative Defaults to `"route"` so routing is relative to the route tree.
* Set to `"path"` to make relative routing operate against path segments.
* @returns The resolved {@link Path} object with `pathname`, `search`, and `hash`
*/
declare function useResolvedPath(to: To, { relative }?: {
relative?: RelativeRoutingType;
}): Path;
/**
* Hook version of {@link Routes | `<Routes>`} that uses objects instead of
* components. These objects have the same properties as the component props.
* The return value of `useRoutes` is either a valid React element you can use
* to render the route tree, or `null` if nothing matched.
*
* @example
* import { useRoutes } from "react-router";
*
* function App() {
* let element = useRoutes([
* {
* path: "/",
* element: <Dashboard />,
* children: [
* {
* path: "messages",
* element: <DashboardMessages />,
* },
* { path: "tasks", element: <DashboardTasks /> },
* ],
* },
* { path: "team", element: <AboutPage /> },
* ]);
*
* return element;
* }
*
* @public
* @category Hooks
* @param routes An array of {@link RouteObject}s that define the route hierarchy
* @param locationArg An optional {@link Location} object or pathname string to
* use instead of the current {@link Location}
* @returns A React element to render the matched route, or `null` if no routes matched
*/
declare function useRoutes(routes: RouteObject[], locationArg?: Partial<Location> | string): React.ReactElement | null;
/**
* Returns the current {@link Navigation}, defaulting to an "idle" navigation
* when no navigation is in progress. You can use this to render pending UI
* (like a global spinner) or read [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData)
* from a form navigation.
*
* @example
* import { useNavigation } from "react-router";
*
* function SomeComponent() {
* let navigation = useNavigation();
* navigation.state;
* navigation.formData;
* // etc.
* }
*
* @public
* @category Hooks
* @mode framework
* @mode data
* @returns The current {@link Navigation} object
*/
declare function useNavigation(): Navigation;
/**
* Revalidate the data on the page for reasons outside of normal data mutations
* like [`Window` focus](https://developer.mozilla.org/en-US/docs/Web/API/Window/focus_event)
* or polling on an interval.
*
* Note that page data is already revalidated automatically after actions.
* If you find yourself using this for normal CRUD operations on your data in
* response to user interactions, you're probably not taking advantage of the
* other APIs like {@link useFetcher}, {@link Form}, {@link useSubmit} that do
* this automatically.
*
* @example
* import { useRevalidator } from "react-router";
*
* function WindowFocusRevalidator() {
* const revalidator = useRevalidator();
*
* useFakeWindowFocus(() => {
* revalidator.revalidate();
* });
*
* return (
* <div hidden={revalidator.state === "idle"}>
* Revalidating...
* </div>
* );
* }
*
* @public
* @category Hooks
* @mode framework
* @mode data
* @returns An object with a `revalidate` function and the current revalidation
* `state`
*/
declare function useRevalidator(): {
revalidate: () => Promise<void>;
state: Router["state"]["revalidation"];
};
/**
* Returns the active route matches, useful for accessing `loaderData` for
* parent/child routes or the route [`handle`](../../start/framework/route-module#handle)
* property
*
* @public
* @category Hooks
* @mode framework
* @mode data
* @returns An array of {@link UIMatch | UI matches} for the current route hierarchy
*/
declare function useMatches(): UIMatch[];
/**
* Returns the data from the closest route
* [`loader`](../../start/framework/route-module#loader) or
* [`clientLoader`](../../start/framework/route-module#clientloader).
*
* @example
* import { useLoaderData } from "react-router";
*
* export async function loader() {
* return await fakeDb.invoices.findAll();
* }
*
* export default function Invoices() {
* let invoices = useLoaderData<typeof loader>();
* // ...
* }
*
* @public
* @category Hooks
* @mode framework
* @mode data
* @returns The data returned from the route's [`loader`](../../start/framework/route-module#loader) or [`clientLoader`](../../start/framework/route-module#clientloader) function
*/
declare function useLoaderData<T = any>(): SerializeFrom<T>;
/**
* Returns the [`loader`](../../start/framework/route-module#loader) data for a
* given route by route ID.
*
* Route IDs are created automatically. They are simply the path of the route file
* relative to the app folder without the extension.
*
* | Route Filename | Route ID |
* | ---------------------------- | ---------------------- |
* | `app/root.tsx` | `"root"` |
* | `app/routes/teams.tsx` | `"routes/teams"` |
* | `app/whatever/teams.$id.tsx` | `"whatever/teams.$id"` |
*
* @example
* import { useRouteLoaderData } from "react-router";
*
* function SomeComponent() {
* const { user } = useRouteLoaderData("root");
* }
*
* // You can also specify your own route ID's manually in your routes.ts file:
* route("/", "containers/app.tsx", { id: "app" })
* useRouteLoaderData("app");
*
* @public
* @category Hooks
* @mode framework
* @mode data
* @param routeId The ID of the route to return loader data from
* @returns The data returned from the specified route's [`loader`](../../start/framework/route-module#loader)
* function, or `undefined` if not found
*/
declare function useRouteLoaderData<T = any>(routeId: string): SerializeFrom<T> | undefined;
/**
* Returns the [`action`](../../start/framework/route-module#action) data from
* the most recent `POST` navigation form submission or `undefined` if there
* hasn't been one.
*
* @example
* import { Form, useActionData } from "react-router";
*
* export async function action({ request }) {
* const body = await request.formData();
* const name = body.get("visitorsName");
* return { message: `Hello, ${name}` };
* }
*
* export default function Invoices() {
* const data = useActionData();
* return (
* <Form method="post">
* <input type="text" name="visitorsName" />
* {data ? data.message : "Waiting..."}
* </Form>
* );
* }
*
* @public
* @category Hooks
* @mode framework
* @mode data
* @returns The data returned from the route's [`action`](../../start/framework/route-module#action)
* function, or `undefined` if no [`action`](../../start/framework/route-module#action)
* has been called
*/
declare function useActionData<T = any>(): SerializeFrom<T> | undefined;
/**
* Accesses the error thrown during an
* [`action`](../../start/framework/route-module#action),
* [`loader`](../../start/framework/route-module#loader),
* or component render to be used in a route module
* [`ErrorBoundary`](../../start/framework/route-module#errorboundary).
*
* @example
* export function ErrorBoundary() {
* const error = useRouteError();
* return <div>{error.message}</div>;
* }
*
* @public
* @category Hooks
* @mode framework
* @mode data
* @returns The error that was thrown during route [loading](../../start/framework/route-module#loader),
* [`action`](../../start/framework/route-module#action) execution, or rendering
*/
declare function useRouteError(): unknown;
/**
* Returns the resolved promise value from the closest {@link Await | `<Await>`}.
*
* @example
* function SomeDescendant() {
* const value = useAsyncValue();
* // ...
* }
*
* // somewhere in your app
* <Await resolve={somePromise}>
* <SomeDescendant />
* </Await>;
*
* @public
* @category Hooks
* @mode framework
* @mode data
* @returns The resolved value from the nearest {@link Await} component
*/
declare function useAsyncValue(): unknown;
/**
* Returns the rejection value from the closest {@link Await | `<Await>`}.
*
* @example
* import { Await, useAsyncError } from "react-router";
*
* function ErrorElement() {
* const error = useAsyncError();
* return (
* <p>Uh Oh, something went wrong! {error.message}</p>
* );
* }
*
* // somewhere in your app
* <Await
* resolve={promiseThatRejects}
* errorElement={<ErrorElement />}
* />;
*
* @public
* @category Hooks
* @mode framework
* @mode data
* @returns The error that was thrown in the nearest {@link Await} component
*/
declare function useAsyncError(): unknown;
/**
* Allow the application to block navigations within the SPA and present the
* user a confirmation dialog to confirm the navigation. Mostly used to avoid
* using half-filled form data. This does not handle hard-reloads or
* cross-origin navigations.
*
* The {@link Blocker} object returned by the hook has the following properties:
*
* - **`state`**
* - `unblocked` - the blocker is idle and has not prevented any navigation
* - `blocked` - the blocker has prevented a navigation
* - `proceeding` - the blocker is proceeding through from a blocked navigation
* - **`location`**
* - When in a `blocked` state, this represents the {@link Location} to which we
* blocked a navigation. When in a `proceeding` state, this is the location
* being navigated to after a `blocker.proceed()` call.
* - **`proceed()`**
* - When in a `blocked` state, you may call `blocker.proceed()` to proceed to the
* blocked location.
* - **`reset()`**
* - When in a `blocked` state, you may call `blocker.reset()` to return the blocker
* back to an `unblocked` state and leave the user at the current location.
*
* @example
* // Boolean version
* const blocker = useBlocker(value !== "");
*
* // Function version
* const blocker = useBlocker(
* ({ currentLocation, nextLocation, historyAction }) =>
* value !== "" &&
* currentLocation.pathname !== nextLocation.pathname
* );
*
* @additionalExamples
* ```tsx
* import { useCallback, useState } from "react";
* import { BlockerFunction, useBlocker } from "react-router";
*
* export function ImportantForm() {
* const [value, setValue] = useState("");
*
* const shouldBlock = useCallback<BlockerFunction>(
* () => value !== "",
* [value]
* );
* const blocker = useBlocker(shouldBlock);
*
* return (
* <form
* onSubmit={(e) => {
* e.preventDefault();
* setValue("");
* if (blocker.state === "blocked") {
* blocker.proceed();
* }
* }}
* >
* <input
* name="data"
* value={value}
* onChange={(e) => setValue(e.target.value)}
* />
*
* <button type="submit">Save</button>
*
* {blocker.state === "blocked" ? (
* <>
* <p style={{ color: "red" }}>
* Blocked the last navigation to
* </p>
* <button
* type="button"
* onClick={() => blocker.proceed()}
* >
* Let me through
* </button>
* <button
* type="button"
* onClick={() => blocker.reset()}
* >
* Keep me here
* </button>
* </>
* ) : blocker.state === "proceeding" ? (
* <p style={{ color: "orange" }}>
* Proceeding through blocked navigation
* </p>
* ) : (
* <p style={{ color: "green" }}>
* Blocker is currently unblocked
* </p>
* )}
* </form>
* );
* }
* ```
*
* @public
* @category Hooks
* @mode framework
* @mode data
* @param shouldBlock Either a boolean or a function returning a boolean which
* indicates whether the navigation should be blocked. The function format
* receives a single object parameter containing the `currentLocation`,
* `nextLocation`, and `historyAction` of the potential navigation.
* @returns A {@link Blocker} object with state and reset functionality
*/
declare function useBlocker(shouldBlock: boolean | BlockerFunction): Blocker;
interface ServerRouterProps {
context: EntryContext;
url: string | URL;
nonce?: string;
}
/**
* The server entry point for a React Router app in Framework Mode. This component
* is used to generate the HTML in the response from the server.
* See [`entry.server.tsx`](../api/framework-conventions/entry.server.tsx).
*
* @public
* @category Framework Routers
* @mode framework
* @param props Props
* @param props.context The entry context containing the manifest, route modules,
* and other data needed for rendering.
* @param props.url The URL of the request being handled.
* @param props.nonce An optional nonce for Content Security Policy (CSP) compliance,
* used to allow inline scripts to run safely.
* @returns A React element that represents the server-rendered application.
*/
declare function ServerRouter({ context, url, nonce, }: ServerRouterProps): ReactElement;
interface StubRouteExtensions {
Component?: RouteComponentType;
HydrateFallback?: HydrateFallbackType;
ErrorBoundary?: ErrorBoundaryType;
loader?: LoaderFunction;
action?: ActionFunction;
children?: StubRouteObject[];
meta?: MetaFunction;
links?: LinksFunction;
}
interface StubIndexRouteObject extends Omit<IndexRouteObject, "Component" | "HydrateFallback" | "ErrorBoundary" | "loader" | "action" | "element" | "errorElement" | "children">, StubRouteExtensions {
}
interface StubNonIndexRouteObject extends Omit<NonIndexRouteObject, "Component" | "HydrateFallback" | "ErrorBoundary" | "loader" | "action" | "element" | "errorElement" | "children">, StubRouteExtensions {
}
type StubRouteObject = StubIndexRouteObject | StubNonIndexRouteObject;
interface RoutesTestStubProps {
/**
* The initial entries in the history stack. This allows you to start a test with
* multiple locations already in the history stack (for testing a back navigation, etc.)
* The test will default to the last entry in initialEntries if no initialIndex is provided.
* e.g. initialEntries={["/home", "/about", "/contact"]}
*/
initialEntries?: InitialEntry[];
/**
* The initial index in the history stack to render. This allows you to start a test at a specific entry.
* It defaults to the last entry in initialEntries.
* e.g.
* initialEntries: ["/", "/events/123"]
* initialIndex: 1 // start at "/events/123"
*/
initialIndex?: number;
/**
* Used to set the route's initial loader and action data.
* e.g. hydrationData={{
* loaderData: { "/contact": { locale: "en-US" } },
* actionData: { "/login": { errors: { email: "invalid email" } }}
* }}
*/
hydrationData?: HydrationState;
/**
* Future flags mimicking the settings in react-router.config.ts
*/
future?: Partial<FutureConfig>;
}
/**
* @category Utils
*/
declare function createRoutesStub(routes: StubRouteObject[], _context?: AppLoadContext | unstable_RouterContextProvider): ({ initialEntries, initialIndex, hydrationData, future, }: RoutesTestStubProps) => React.JSX.Element;
interface CookieSignatureOptions {
/**
* An array of secrets that may be used to sign/unsign the value of a cookie.
*
* The array makes it easy to rotate secrets. New secrets should be added to
* the beginning of the array. `cookie.serialize()` will always use the first
* value in the array, but `cookie.parse()` may use any of them so that
* cookies that were signed with older secrets still work.
*/
secrets?: string[];
}
type CookieOptions = ParseOptions & SerializeOptions & CookieSignatureOptions;
/**
* A HTTP cookie.
*
* A Cookie is a logical container for metadata about a HTTP cookie; its name
* and options. But it doesn't contain a value. Instead, it has `parse()` and
* `serialize()` methods that allow a single instance to be reused for
* parsing/encoding multiple different values.
*
* @see https://remix.run/utils/cookies#cookie-api
*/
interface Cookie {
/**
* The name of the cookie, used in the `Cookie` and `Set-Cookie` headers.
*/
readonly name: string;
/**
* True if this cookie uses one or more secrets for verification.
*/
readonly isSigned: boolean;
/**
* The Date this cookie expires.
*
* Note: This is calculated at access time using `maxAge` when no `expires`
* option is provided to `createCookie()`.
*/
readonly expires?: Date;
/**
* Parses a raw `Cookie` header and returns the value of this cookie or
* `null` if it's not present.
*/
parse(cookieHeader: string | null, options?: ParseOptions): Promise<any>;
/**
* Serializes the given value to a string and returns the `Set-Cookie`
* header.
*/
serialize(value: any, options?: SerializeOptions): Promise<string>;
}
/**
* Creates a logical container for managing a browser cookie from the server.
*/
declare const createCookie: (name: string, cookieOptions?: CookieOptions) => Cookie;
type IsCookieFunction = (object: any) => object is Cookie;
/**
* Returns true if an object is a Remix cookie container.
*
* @see https://remix.run/utils/cookies#iscookie
*/
declare const isCookie: IsCookieFunction;
type RequestHandler = (request: Request, loadContext?: MiddlewareEnabled extends true ? unstable_InitialContext : AppLoadContext) => Promise<Response>;
type CreateRequestHandlerFunction = (build: ServerBuild | (() => ServerBuild | Promise<ServerBuild>), mode?: string) => RequestHandler;
declare const createRequestHandler: CreateRequestHandlerFunction;
/**
* An object of name/value pairs to be used in the session.
*/
interface SessionData {
[name: string]: any;
}
/**
* Session persists data across HTTP requests.
*
* @see https://reactrouter.com/explanation/sessions-and-cookies#sessions
*/
interface Session<Data = SessionData, FlashData = Data> {
/**
* A unique identifier for this session.
*
* Note: This will be the empty string for newly created sessions and
* sessions that are not backed by a database (i.e. cookie-based sessions).
*/
readonly id: string;
/**
* The raw data contained in this session.
*
* This is useful mostly for SessionStorage internally to access the raw
* session data to persist.
*/
readonly data: FlashSessionData<Data, FlashData>;
/**
* Returns `true` if the session has a value for the given `name`, `false`
* otherwise.
*/
has(name: (keyof Data | keyof FlashData) & string): boolean;
/**
* Returns the value for the given `name` in this session.
*/
get<Key extends (keyof Data | keyof FlashData) & string>(name: Key): (Key extends keyof Data ? Data[Key] : undefined) | (Key extends keyof FlashData ? FlashData[Key] : undefined) | undefined;
/**
* Sets a value in the session for the given `name`.
*/
set<Key extends keyof Data & string>(name: Key, value: Data[Key]): void;
/**
* Sets a value in the session that is only valid until the next `get()`.
* This can be useful for temporary values, like error messages.
*/
flash<Key extends keyof FlashData & string>(name: Key, value: FlashData[Key]): void;
/**
* Removes a value from the session.
*/
unset(name: keyof Data & string): void;
}
type FlashSessionData<Data, FlashData> = Partial<Data & {
[Key in keyof FlashData as FlashDataKey<Key & string>]: FlashData[Key];
}>;
type FlashDataKey<Key extends string> = `__flash_${Key}__`;
type CreateSessionFunction = <Data = SessionData, FlashData = Data>(initialData?: Data, id?: string) => Session<Data, FlashData>;
/**
* Creates a new Session object.
*
* Note: This function is typically not invoked directly by application code.
* Instead, use a `SessionStorage` object's `getSession` method.
*/
declare const createSession: CreateSessionFunction;
type IsSessionFunction = (object: any) => object is Session;
/**
* Returns true if an object is a React Router session.
*
* @see https://reactrouter.com/api/utils/isSession
*/
declare const isSession: IsSessionFunction;
/**
* SessionStorage stores session data between HTTP requests and knows how to
* parse and create cookies.
*
* A SessionStorage creates Session objects using a `Cookie` header as input.
* Then, later it generates the `Set-Cookie` header to be used in the response.
*/
interface SessionStorage<Data = SessionData, FlashData = Data> {
/**
* Parses a Cookie header from a HTTP request and returns the associated
* Session. If there is no session associated with the cookie, this will
* return a new Session with no data.
*/
getSession: (cookieHeader?: string | null, options?: ParseOptions) => Promise<Session<Data, FlashData>>;
/**
* Stores all data in the Session and returns the Set-Cookie header to be
* used in the HTTP response.
*/
commitSession: (session: Session<Data, FlashData>, options?: SerializeOptions) => Promise<string>;
/**
* Deletes all data associated with the Session and returns the Set-Cookie
* header to be used in the HTTP response.
*/
destroySession: (session: Session<Data, FlashData>, options?: SerializeOptions) => Promise<string>;
}
/**
* SessionIdStorageStrategy is designed to allow anyone to easily build their
* own SessionStorage using `createSessionStorage(strategy)`.
*
* This strategy describes a common scenario where the session id is stored in
* a cookie but the actual session data is stored elsewhere, usually in a
* database or on disk. A set of create, read, update, and delete operations
* are provided for managing the session data.
*/
interface SessionIdStorageStrategy<Data = SessionData, FlashData = Data> {
/**
* The Cookie used to store the session id, or options used to automatically
* create one.
*/
cookie?: Cookie | (CookieOptions & {
name?: string;
});
/**
* Creates a new record with the given data and returns the session id.
*/
createData: (data: FlashSessionData<Data, FlashData>, expires?: Date) => Promise<string>;
/**
* Returns data for a given session id, or `null` if there isn't any.
*/
readData: (id: string) => Promise<FlashSessionData<Data, FlashData> | null>;
/**
* Updates data for the given session id.
*/
updateData: (id: string, data: FlashSessionData<Data, FlashData>, expires?: Date) => Promise<void>;
/**
* Deletes data for a given session id from the data store.
*/
deleteData: (id: string) => Promise<void>;
}
/**
* Creates a SessionStorage object using a SessionIdStorageStrategy.
*
* Note: This is a low-level API that should only be used if none of the
* existing session storage options meet your requirements.
*/
declare function createSessionStorage<Data = SessionData, FlashData = Data>({ cookie: cookieArg, createData, readData, updateData, deleteData, }: SessionIdStorageStrategy<Data, FlashData>): SessionStorage<Data, FlashData>;
interface CookieSessionStorageOptions {
/**
* The Cookie used to store the session data on the client, or options used
* to automatically create one.
*/
cookie?: SessionIdStorageStrategy["cookie"];
}
/**
* Creates and returns a SessionStorage object that stores all session data
* directly in the session cookie itself.
*
* This has the advantage that no database or other backend services are
* needed, and can help to simplify some load-balanced scenarios. However, it
* also has the limitation that serialized session data may not exceed the
* browser's maximum cookie size. Trade-offs!
*/
declare function createCookieSessionStorage<Data = SessionData, FlashData = Data>({ cookie: cookieArg }?: CookieSessionStorageOptions): SessionStorage<Data, FlashData>;
interface MemorySessionStorageOptions {
/**
* The Cookie used to store the session id on the client, or options used
* to automatically create one.
*/
cookie?: SessionIdStorageStrategy["cookie"];
}
/**
* Creates and returns a simple in-memory SessionStorage object, mostly useful
* for testing and as a reference implementation.
*
* Note: This storage does not scale beyond a single process, so it is not
* suitable for most production scenarios.
*/
declare function createMemorySessionStorage<Data = SessionData, FlashData = Data>({ cookie }?: MemorySessionStorageOptions): SessionStorage<Data, FlashData>;
type DevServerHooks = {
getCriticalCss?: (pathname: string) => Promise<string | undefined>;
processRequestError?: (error: unknown) => void;
};
declare function setDevServerHooks(devServerHooks: DevServerHooks): void;
type Args = {
[K in keyof Pages]: ToArgs<Pages[K]["params"]>;
};
type ToArgs<Params extends Record<string, string | undefined>> = Equal<Params, {}> extends true ? [] : Partial<Params> extends Params ? [Params] | [] : [
Params
];
/**
Returns a resolved URL path for the specified route.
```tsx
const h = href("/:lang?/about", { lang: "en" })
// -> `/en/about`
<Link to={href("/products/:id", { id: "abc123" })} />
```
*/
declare function href<Path extends keyof Args>(path: Path, ...args: Args[Path]): string;
type BrowserCreateFromReadableStreamFunction = (body: ReadableStream<Uint8Array>, { temporaryReferences, }: {
temporaryReferences: unknown;
}) => Promise<unknown>;
type EncodeReplyFunction = (args: unknown[], options: {
temporaryReferences: unknown;
}) => Promise<BodyInit>;
/**
* Create a React `callServer` implementation for React Router.
*
* @example
* import {
* createFromReadableStream,
* createTemporaryReferenceSet,
* encodeReply,
* setServerCallback,
* } from "@vitejs/plugin-rsc/browser";
* import { unstable_createCallServer as createCallServer } from "react-router";
*
* setServerCallback(
* createCallServer({
* createFromReadableStream,
* createTemporaryReferenceSet,
* encodeReply,
* })
* );
*
* @name unstable_createCallServer
* @public
* @category RSC
* @mode data
* @param opts Options
* @param opts.createFromReadableStream Your `react-server-dom-xyz/client`'s
* `createFromReadableStream`. Used to decode payloads from the server.
* @param opts.createTemporaryReferenceSet A function that creates a temporary
* reference set for the RSC payload.
* @param opts.encodeReply Your `react-server-dom-xyz/client`'s `encodeReply`.
* Used when sending payloads to the server.
* @param opts.fetch Optional fetch implementation. Defaults to global `fetch`.
* @returns A function that can be used to call server actions.
*/
declare function createCallServer({ createFromReadableStream, createTemporaryReferenceSet, encodeReply, fetch: fetchImplementation, }: {
createFromReadableStream: BrowserCreateFromReadableStreamFunction;
createTemporaryReferenceSet: () => unknown;
encodeReply: EncodeReplyFunction;
fetch?: (request: Request) => Promise<Response>;
}): (id: string, args: unknown[]) => Promise<unknown>;
/**
* Props for the `unstable_RSCHydratedRouter` component.
* @name unstable_RSCHydratedRouterProps
*/
interface RSCHydratedRouterProps {
/**
* Your `react-server-dom-xyz/client`'s `createFromReadableStream` function,
* used to decode payloads from the server.
*/
createFromReadableStream: BrowserCreateFromReadableStreamFunction;
/**
* Optional fetch implementation. Defaults to global `fetch`.
*/
fetch?: (request: Request) => Promise<Response>;
/**
* The decoded `RSCPayload` to hydrate.
*/
payload: RSCPayload;
/**
* `eager` or `lazy` - Determines if links are eagerly discovered, or delayed
* until clicked.
*/
routeDiscovery?: "eager" | "lazy";
/**
* A function that returns an `unstable_InitialContext` object
* (`Map<RouterContext, unknown>`), for use in client loaders, actions and
* middleware.
*/
unstable_getContext?: RouterInit["unstable_getContext"];
}
/**
* Hydrates a server rendered `RSCPayload` in the browser.
*
* @example
* import { startTransition, StrictMode } from "react";
* import { hydrateRoot } from "react-dom/client";
* import {
* unstable_getRSCStream as getRSCStream,
* unstable_RSCHydratedRouter as RSCHydratedRouter,
* } from "react-router";
* import type { unstable_RSCPayload as RSCPayload } from "react-router";
*
* createFromReadableStream(getRSCStream()).then(
* (payload: RSCServerPayload) => {
* startTransition(async () => {
* hydrateRoot(
* document,
* <StrictMode>
* <RSCHydratedRouter
* createFromReadableStream={
* createFromReadableStream
* }
* payload={payload}
* />
* </StrictMode>,
* {
* formState: await getFormState(payload),
* }
* );
* });
* }
* );
*
* @name unstable_RSCHydratedRouter
* @public
* @category RSC
* @mode data
* @param props Props
* @param {unstable_RSCHydratedRouterProps.createFromReadableStream} props.createFromReadableStream n/a
* @param {unstable_RSCHydratedRouterProps.fetch} props.fetch n/a
* @param {unstable_RSCHydratedRouterProps.payload} props.payload n/a
* @param {unstable_RSCHydratedRouterProps.routeDiscovery} props.routeDiscovery n/a
* @param {unstable_RSCHydratedRouterProps.unstable_getContext} props.unstable_getContext n/a
* @returns A hydrated router that can be used to navigate and render routes.
*/
declare function RSCHydratedRouter({ createFromReadableStream, fetch: fetchImplementation, payload, routeDiscovery, unstable_getContext, }: RSCHydratedRouterProps): React.JSX.Element;
type SSRCreateFromReadableStreamFunction = (body: ReadableStream<Uint8Array>) => Promise<unknown>;
/**
* Routes the incoming request to the RSC server and appropriately proxies the
* server response for data / resource requests, or renders to HTML for a document
* request.
*
* @example
* import { createFromReadableStream } from "@vitejs/plugin-rsc/ssr";
* import * as ReactDomServer from "react-dom/server.edge";
* import {
* unstable_RSCStaticRouter as RSCStaticRouter,
* unstable_routeRSCServerRequest as routeRSCServerRequest,
* } from "react-router";
*
* routeRSCServerRequest({
* request,
* fetchServer,
* createFromReadableStream,
* async renderHTML(getPayload) {
* const payload = await getPayload();
*
* return await renderHTMLToReadableStream(
* <RSCStaticRouter getPayload={getPayload} />,
* {
* bootstrapScriptContent,
* formState: await getFormState(payload),
* }
* );
* },
* });
*
* @name unstable_routeRSCServerRequest
* @public
* @category RSC
* @mode data
* @param opts Options
* @param opts.createFromReadableStream Your `react-server-dom-xyz/client`'s
* `createFromReadableStream` function, used to decode payloads from the server.
* @param opts.fetchServer A function that forwards a `Request` to the RSC handler
* and returns a `Promise<Response>` containing a serialized `RSCPayload`.
* @param opts.renderHTML A function that renders the `RSCPayload` to HTML, usually
* using a `<RSCStaticRouter>`.
* @param opts.request The request to route.