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
|
---|