Early in the process of redesigning our developer dashboard, we came to a realization: The engineering effort needed to implement our exciting new design changes would entail more than just a few stylistic tweaks — a dilemma that many of our fellow engineers know all too well. There would be a handful of technical challenges we had to face during the redesign, especially when it came to routing.
“Oh, just move the navigation bar,” we said. “Just pull out a few parent routes here and add a few child routes there. We’ll be able to implement the entire redesign in a day — two days max, right?”
As the previous episode of our “What the React” series outlined, we wanted to eliminate as much friction from our developer experience as possible, starting with removing our
/apps route. In our old dashboard, the
/apps route was where you had to select your desired app from a list of all your applications, whenever you logged in. Thanks to the redesign, you don’t have to make that choice anymore. Instead, we make an educated guess of which app you’d like to view, based on which application you’ve most recently interacted with.
What’s more, each app in our dashboard now also contains a few nested routes of its own (think: app credentials and app settings) to organize content within that application more clearly.
To help you visualize this, here’s the original flow:
And here’s the new and improved flow:
From a user standpoint, this is great. Now you get well-organized content and spend fewer clicks getting where you need to go within our dashboard.
From an engineering standpoint, however, improving this flow was no walk in the park. Our routing needed more than just a few tweaks. Specifically, we had to:
- Replace the
/appsroute with an
/apps/:idroute in our top-level router.
- Allow you to navigate to nested routes within an application (e.g.
- If you go to an invalid nested route (e.g.
/apps/:id/incorrect-nested-route) or enter the
/apps/:idroute without specifying a nested route, we should send you to a default nested route (
- If you go to a route with an invalid app id (e.g.
/apps/invalid-id), we should tell you the application couldn’t be found and direct you to another app.
- If you go to a top-level route that isn’t defined (e.g.
/not-defined), we should route you to your most recently viewed app, as we do on login.
So, before we knew it, we had a very long to-do list of routing adjustments.
Enter React Router.
Elegant Nested Routing
One extremely neat feature of React Router is that it allows for nested routing. For us, this meant that we could define our
/apps/:id route — which renders the Application component — at the highest level of our dashboard’s routing. Then, in the render method of Application, we could define nested routes for every possible view within an app, each with its own respective component. For example,
apps/:id/credentials renders the Credentials component and
apps/:id/settings renders the Settings component.
On top of this, using nested routes allows us to verify that you have navigated to a valid app ID in the Application component, before we send you to a nested route. If the app ID in the route is invalid, we won’t send you to a nested route, but will instead prompt you to choose a valid app or register a new app.
Another benefit of using nested routing with React Router is the ability to redirect differently in the nested routes and the top-level routes.
At the nested level, we can redirect you to a default view within an application:
- If your nested route is not specified in the URL, we redirect to the default
- If your nested route is not defined in our dashboard, we also redirect to the default
At the top-level, we can redirect based on your authentication:
- If your authentication access token has expired, we redirect you to
- If you are still logged in, but attempt to go to
/signup, or another public route, we redirect you to your most recently viewed application.
In order to do this, we wrote functional wrapper components —
<PrivateRoute/> — around React Router’s
<Route/>. If you are properly authenticated, these wrapper components will render the component corresponding to your route. If you aren’t properly authenticated, the wrapper components will render the specified redirect. They look something like this:
Putting this all together, we get our top-level routes — each with their own path, authentication check, component, and redirect:
We ❤️ React Router
Long story short, we love React Router and its straightforward solutions for nested routes and redirecting.
With its help, adding new routes and tweaking old routes was a piece of cake! We tackled our seemingly very complicated to-do list of routing changes and got to work on our redesign styling in no time.
Blockers: gone 🚫
Our redesigned developer dashboard: shipped 🚢
Smartcar is an API that allows mobile and web apps to communicate with connected cars (think “check odometer” or “unlock doors”) — across vehicle brands, hardware-free.