When to use Route Modal in React Router
With the introduction of nested routes in React Router v6 and Remix, using routes as modals has become a common pattern. The idea is quite simple, let's say you have a page /users
and when you choose an user you open a modal with the user details.
Typically, you set some state in a component, then if that state is not null
, you render <UserModal id={userId} />
and inside UserModal you fetch the data of the user. This means that you now need to have a loading state inside your modal component to show while the user data is being fetched.
Another way to build this is that you already have the user details data in the page rendering the list of users, so you can pass the data to the modal directly <UserModal user={user} />
.
While this removes the need for more data fetching and loadings states, it also means you're loading data you might never use, because if your list show the user avatar, name and email per users and the modal show another ten fields, you're loading those ten fields per user in the list, even if you never open the modal.
This is where a route modal comes in, you can move your UserModal
to be a nested route inside the /users
page, this way opening a modal would be a matter of navigating to /users/:userId
, and closing it would be navigating back to /users
.
Some nice benefits of this pattern is that you can do the data fetching in the child route loader provided to you by the router, so the loading state can be shown directly in the list item, and you only load the data you need when you need it, your list can focus on those three fields of the user, no more overfetching.
Another benefit of route modals is that you get a linkeable state, if someone wants to share a link to show the user details for a specific user is now possible because it will have a unique URL like /users/1
that the app can use to open the modal directly in the correct state, you could achieve this by changing the URL when opening the modal or when changing the selected user, but the route already has this built-in.
Should you Always use Route Modals?
With this pattern in mind, you might be tempted to always use route modals, but there are some cases where it might not be the best choice.
Let's say you want to show a confirmation modal when you delete a user, you could use a route modal for this and take the user to /users/delete/:userId
, or maybe use search params like /users?delete=$userId
, the first one would require adding a new route for a modal that doesn't need extra data, and the second (at least in React Router) would cause the route to reload every route loader in case it depends on the search params.
When should I use a Route Modal?
My rule of thumb is to use route modals when you need to fetch more data, and most importantly, when you want to be able to share a URL that will show the modal open. If you don't want your app users to share a link to /users?delete=1
or /users/delete/1
then use a state, if you want to be able to share a link to /users/1
to show the details then use a route modal.
Loading extra data is another great benefit of this pattern, and while sometimes you may not want to have shareable URLs, you may still need to fetch data, if it's only one or two extra fields you may be ok with a little bit of overfetching on your list, but if you're loading a lot of extra data, then a route modal is a handy pattern to use in your app.
For cases where you already have all the data you need, and there's not a reason to have a shareable URLs, simply use a state and open the modal conditionally based on that.