What is @remix-run/router?
The @remix-run/router package is a powerful routing library designed for the Remix framework, which is used for building modern web applications. It provides robust features for handling URL routing, navigation, and data loading in a React environment. The router is designed to work seamlessly with both client-side and server-side rendering, offering a flexible and efficient way to manage routes in a web application.
What are @remix-run/router's main functionalities?
Route Matching
This feature allows developers to define a set of routes and corresponding components. The router matches the current URL to the defined routes and renders the appropriate component.
import { createBrowserRouter, RouterProvider, Route } from '@remix-run/router';
const router = createBrowserRouter([
{
path: '/',
element: <Home />
},
{
path: '/about',
element: <About />
}
]);
function App() {
return <RouterProvider router={router} />;
}
Nested Routes
Nested routes allow for the organization of components into a hierarchy, matching nested paths to nested components, which is useful for creating complex layouts with sub-routes.
import { createBrowserRouter, RouterProvider, Route } from '@remix-run/router';
const router = createBrowserRouter([
{
path: 'dashboard',
element: <DashboardLayout />,
children: [
{ path: 'stats', element: <Stats /> },
{ path: 'reports', element: <Reports /> }
]
}
]);
function App() {
return <RouterProvider router={router} />;
}
Data Loading
This feature supports defining data loading functions directly within the route configuration. These functions fetch necessary data before rendering the route's component, ensuring the component has all data it needs on initial render.
import { createBrowserRouter, RouterProvider, Route } from '@remix-run/router';
const router = createBrowserRouter([
{
path: '/profile',
element: <Profile />,
loader: async () => {
const data = await fetchUserProfile();
return data;
}
}
]);
function App() {
return <RouterProvider router={router} />;
}
Other packages similar to @remix-run/router
react-router
React Router is one of the most popular routing solutions for React applications. It offers similar functionalities to @remix-run/router, such as dynamic route matching, nested routes, and server-side rendering support. However, React Router operates more broadly within the React ecosystem, whereas @remix-run/router is specifically optimized for the Remix framework.
Router
The @remix-run/router
package is the heart of React Router and provides all the core functionality for routing, data loading, data mutations, and navigation.
If you're using React Router, you should never import
anything directly from
the @remix-run/router
or react-router
packages, but you should have everything
you need in either react-router-dom
or react-router-native
. Both of those
packages re-export everything from @remix-run/router
and react-router
.
API
A Router instance can be created using createRouter
:
let router = createRouter({
routes,
history,
hydrationData?: HydrationState;
}).initialize()
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()
;
interface RouterState {
historyAction: Action;
location: Location;
matches: DataRouteMatch[];
initialized: boolean;
navigation: Navigation;
revalidation: RevalidationState;
restoreScrollPosition: number | false | null;
resetScrollPosition: boolean;
loaderData: RouteData;
actionData: RouteData | null;
errors: RouteData | null;
fetchers: Map<string, Fetcher>;
}
Navigations
All navigations are done through the router.navigate
API which is overloaded to support different types of navigations:
router.navigate("/page");
router.navigate("/page", { replace: true });
router.navigate(-1);
let formData = new FormData();
formData.append(key, value);
router.navigate("/page", {
formMethod: "post",
formData,
});
Fetchers
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.
router.fetch("key", "/page");
let formData = new FormData();
formData.append(key, value);
router.fetch("key", "/page", {
formMethod: "post",
formData,
});
Revalidation
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.