The React Router Repeats Itself, First as Tragedy, Second as Farce

Graham Mendick
3 min readMar 29, 2020

--

Stuck in self-isolation, you’d be forgiven for thinking things couldn’t get much weirder. But wait until you see how weird things are going to get when React Router v6 lands.

Do you remember when the React Router team brought out version 4? They threw away static configuration and went all-in on Route components. They insisted the change was necessary to support upcoming React functionality — now known as Suspense. Well, guess what. The React Router team is bringing back static configuration in v6. It turns out their current API doesn’t support Suspense. I told you things were going to get weird.

You see, the real problem with the React Router was never static configuration. The real problem was the way it used static configuration and version 6 isn’t going to fix that. I’m going to show you a new approach to static configuration brought to you by the Navigation router.

Named Routes

To demonstrate the Navigation router’s new approach to static configuration, I’ll build an example web application. It has two pages. The first renders a list of people. Selecting a person, takes you to the second page which displays their details. At the bottom of this page is a section you can expand to reveal a list of their friends.

If I was using the React Router, I’d have to decide what my routes look like before I could start coding. The Navigation router thinks it’s too early for all that. At this stage, the Navigation router only asks me to configure the two pages.

const states = [
{ key: 'list' },
{ key: 'details' }
};

Even though I haven’t configured any routes yet, I can still render Hyperlinks. Instead of hard-coding the route, I build a Hyperlink by specifying the page I want to go to and the data I need to pass. For example, in the Hyperlink that navigates to the details page, I pass the id of the selected person.

<NavigationLink
stateKey="details"
navigationData={{ id: 3 }} />

The Hyperlink at the bottom of the details page looks similar. The only difference is that I pass an additional boolean to indicate I should expand the friends section.

<NavigationLink
stateKey="details"
navigationData={{ id: 3, friends: true }} />

Flat Configuration

How do the Hyperlinks work when I haven’t configured a single route yet? The Navigation router assigns each page a default route and creates temporary Urls by passing all data in the query string. For example, the interim Url that selects the person with id 3 is ‘/details?id=3’. As soon as I configure the real routes the Navigation router ignores the defaults and starts using mine instead.

So let’s assume that I’ve finished building the Listing and Details components. Now the app is up and running its time to assign the real routes. I’ll configure a route for the details page so that the Navigation router generates a Url of ‘/person/3’ instead of ‘/details?id=3’.

const states = [
{ key: 'list' },
{ key: 'details', route: 'person/{id}' }
};

The app is still working. There aren’t any hard-coded Urls so I don’t have to change any component code.

I also want to fix up the Url that expands the friends section at the bottom of the details page. It currently looks like ‘/person/3?friends=true’ but I want it to be ‘/person/3/true’. With the React Router you’d have to nest your configuration. The Navigation router doesn’t believe in nested configuration. Instead, I configure the nested route using the ‘+’ separator.

{ key: 'details', route: 'person/{id}+/{friends}' }

The Navigation router effectively assigns both routes ‘person/{id}’ and ‘person/{id}/{friends}’ to the details page.

React Router v6

What’s included in React Router v6 apart from a return to static configuration? It comes with a couple of new features called Relative Links and Path Ranking. I hope that the React Router team takes a good look at the Navigation router approach to static configuration. If they do, they’ll see that Relative Links are a poor substitute for Named Routes and that Flat Configuration makes Path Ranking redundant.

--

--