[d565449] | 1 | # Remix Router
|
---|
| 2 |
|
---|
| 3 | The `@remix-run/router` package is a framework-agnostic routing package (sometimes referred to as a browser-emulator) that serves as the heart of [React Router][react-router] and [Remix][remix] and provides all the core functionality for routing coupled with data loading and data mutations. It comes with built-in handling of errors, race-conditions, interruptions, cancellations, lazy-loading data, and much, much more.
|
---|
| 4 |
|
---|
| 5 | If you're using React Router, you should never `import` anything directly from the `@remix-run/router` - you should have everything you need in `react-router-dom` (or `react-router`/`react-router-native` if you're not rendering in the browser). All of those packages should re-export everything you would otherwise need from `@remix-run/router`.
|
---|
| 6 |
|
---|
| 7 | > [!WARNING]
|
---|
| 8 | >
|
---|
| 9 | > This router is a low-level package intended to be consumed by UI layer routing libraries. You should very likely not be using this package directly unless you are authoring a routing library such as [`react-router-dom`][react-router-repo] or one of it's other [UI ports][remix-routers-repo].
|
---|
| 10 |
|
---|
| 11 | ## API
|
---|
| 12 |
|
---|
| 13 | A Router instance can be created using `createRouter`:
|
---|
| 14 |
|
---|
| 15 | ```js
|
---|
| 16 | // Create and initialize a router. "initialize" contains all side effects
|
---|
| 17 | // including history listeners and kicking off the initial data fetch
|
---|
| 18 | let router = createRouter({
|
---|
| 19 | // Required properties
|
---|
| 20 | routes: [{
|
---|
| 21 | path: '/',
|
---|
| 22 | loader: ({ request, params }) => { /* ... */ },
|
---|
| 23 | children: [{
|
---|
| 24 | path: 'home',
|
---|
| 25 | loader: ({ request, params }) => { /* ... */ },
|
---|
| 26 | }]
|
---|
| 27 | },
|
---|
| 28 | history: createBrowserHistory(),
|
---|
| 29 |
|
---|
| 30 | // Optional properties
|
---|
| 31 | basename, // Base path
|
---|
| 32 | mapRouteProperties, // Map framework-agnostic routes to framework-aware routes
|
---|
| 33 | future, // Future flags
|
---|
| 34 | hydrationData, // Hydration data if using server-side-rendering
|
---|
| 35 | }).initialize();
|
---|
| 36 | ```
|
---|
| 37 |
|
---|
| 38 | Internally, the Router represents the state in an object of the following format, which is available through `router.state`. You can also register a subscriber of the signature `(state: RouterState) => void` to execute when the state updates via `router.subscribe()`;
|
---|
| 39 |
|
---|
| 40 | ```ts
|
---|
| 41 | interface RouterState {
|
---|
| 42 | // False during the initial data load, true once we have our initial data
|
---|
| 43 | initialized: boolean;
|
---|
| 44 | // The `history` action of the most recently completed navigation
|
---|
| 45 | historyAction: Action;
|
---|
| 46 | // The current location of the router. During a navigation this reflects
|
---|
| 47 | // the "old" location and is updated upon completion of the navigation
|
---|
| 48 | location: Location;
|
---|
| 49 | // The current set of route matches
|
---|
| 50 | matches: DataRouteMatch[];
|
---|
| 51 | // The state of the current navigation
|
---|
| 52 | navigation: Navigation;
|
---|
| 53 | // The state of any in-progress router.revalidate() calls
|
---|
| 54 | revalidation: RevalidationState;
|
---|
| 55 | // Data from the loaders for the current matches
|
---|
| 56 | loaderData: RouteData;
|
---|
| 57 | // Data from the action for the current matches
|
---|
| 58 | actionData: RouteData | null;
|
---|
| 59 | // Errors thrown from loaders/actions for the current matches
|
---|
| 60 | errors: RouteData | null;
|
---|
| 61 | // Map of all active fetchers
|
---|
| 62 | fetchers: Map<string, Fetcher>;
|
---|
| 63 | // Scroll position to restore to for the active Location, false if we
|
---|
| 64 | // should not restore, or null if we don't have a saved position
|
---|
| 65 | // Note: must be enabled via router.enableScrollRestoration()
|
---|
| 66 | restoreScrollPosition: number | false | null;
|
---|
| 67 | // Proxied `preventScrollReset` value passed to router.navigate()
|
---|
| 68 | preventScrollReset: boolean;
|
---|
| 69 | }
|
---|
| 70 | ```
|
---|
| 71 |
|
---|
| 72 | ### Navigations
|
---|
| 73 |
|
---|
| 74 | All navigations are done through the `router.navigate` API which is overloaded to support different types of navigations:
|
---|
| 75 |
|
---|
| 76 | ```js
|
---|
| 77 | // Link navigation (pushes onto the history stack by default)
|
---|
| 78 | router.navigate("/page");
|
---|
| 79 |
|
---|
| 80 | // Link navigation (replacing the history stack)
|
---|
| 81 | router.navigate("/page", { replace: true });
|
---|
| 82 |
|
---|
| 83 | // Pop navigation (moving backward/forward in the history stack)
|
---|
| 84 | router.navigate(-1);
|
---|
| 85 |
|
---|
| 86 | // Form submission navigation
|
---|
| 87 | let formData = new FormData();
|
---|
| 88 | formData.append(key, value);
|
---|
| 89 | router.navigate("/page", {
|
---|
| 90 | formMethod: "post",
|
---|
| 91 | formData,
|
---|
| 92 | });
|
---|
| 93 |
|
---|
| 94 | // Relative routing from a source routeId
|
---|
| 95 | router.navigate("../../somewhere", {
|
---|
| 96 | fromRouteId: "active-route-id",
|
---|
| 97 | });
|
---|
| 98 | ```
|
---|
| 99 |
|
---|
| 100 | ### Fetchers
|
---|
| 101 |
|
---|
| 102 | Fetchers are a mechanism to call loaders/actions without triggering a navigation, and are done through the `router.fetch()` API. All fetch calls require a unique key to identify the fetcher.
|
---|
| 103 |
|
---|
| 104 | ```js
|
---|
| 105 | // Execute the loader for /page
|
---|
| 106 | router.fetch("key", "/page");
|
---|
| 107 |
|
---|
| 108 | // Submit to the action for /page
|
---|
| 109 | let formData = new FormData();
|
---|
| 110 | formData.append(key, value);
|
---|
| 111 | router.fetch("key", "/page", {
|
---|
| 112 | formMethod: "post",
|
---|
| 113 | formData,
|
---|
| 114 | });
|
---|
| 115 | ```
|
---|
| 116 |
|
---|
| 117 | ### Revalidation
|
---|
| 118 |
|
---|
| 119 | By default, active loaders will revalidate after any navigation or fetcher mutation. If you need to kick off a revalidation for other use-cases, you can use `router.revalidate()` to re-execute all active loaders.
|
---|
| 120 |
|
---|
| 121 | ### Future Flags
|
---|
| 122 |
|
---|
| 123 | We use _Future Flags_ in the router to help us introduce breaking changes in an opt-in fashion ahead of major releases. Please check out the [blog post][future-flags-post] and [React Router Docs][api-development-strategy] for more information on this process. The currently available future flags in `@remix-run/router` are:
|
---|
| 124 |
|
---|
| 125 | | Flag | Description |
|
---|
| 126 | | ------------------------ | ------------------------------------------------------------------------- |
|
---|
| 127 | | `v7_normalizeFormMethod` | Normalize `useNavigation().formMethod` to be an uppercase HTTP Method |
|
---|
| 128 | | `v7_prependBasename` | Prepend the `basename` to incoming `router.navigate`/`router.fetch` paths |
|
---|
| 129 |
|
---|
| 130 | [react-router]: https://reactrouter.com
|
---|
| 131 | [remix]: https://remix.run
|
---|
| 132 | [react-router-repo]: https://github.com/remix-run/react-router
|
---|
| 133 | [remix-routers-repo]: https://github.com/brophdawg11/remix-routers
|
---|
| 134 | [api-development-strategy]: https://reactrouter.com/en/main/guides/api-development-strategy
|
---|
| 135 | [future-flags-post]: https://remix.run/blog/future-flags
|
---|