react router

How to create a simple React Router

NOTICE
Want to read a thorough explanation? Keep reading.
Just want the code? Click here to skip to the bottom.

React is meant to create single page applications but when using a href to link your pages, it becomes a multi-page application that needs to reload with each link. That defeats part of the purpose of React. The solution to this is using React Routers. Let’s learn how to use them!

Set Up

First do your usual npm create-react-app My-Router-Project and get your basic code editor set up ready.

Now we’re going to use an npm package, so make sure you’re cd’d into your project and in the terminal type npm install react-router-dom. It can sometimes take a while , so you can wait for it to finish or start the next part while it’s loading.

At this point, your App.js should have the most basic setup like this.

import React from "react";
import "./styles.css";

export default function App() {
  return (
    <div className="App">
      <h1>React Routing</h1>
      <h2>Learning how to use React Routers</h2>
    </div>
  );
}

For our project, let’s create two files. A Home.js and an About.js under src. If you want to put them in a Page or Component folder, that’s fine too.

Add the basic page structure to your Home.js and About.js. They should look like this.

import React from "react";

export default function Home() {
  return (
    <div>
      <h1>Home</h1>
      <p>Home is where the heart is</p>
    </div>
  );
}

Note that where it says Home, replace it with About for the About page.

Ok, now that those are created, you can close them. We will be working from the App.js file the rest of the time. Home and About are just giving our router places to go.

Routes

Let’s import what we need from the react-router-dom package. In App.js under your other imports, add this.

import {Route, BrowserRouter as Router} from "react-router-dom";

Notice BrowserRouter as Router. All we did was give BrowserRouter a nickname so we don’t have to type BrowerRouter all the time. Even saying it feels time consuming.

Now wrap your container inside a <Router> component. It should now look like this.

return (
    <Router>
      <div className="App">
        <h1>React Routing</h1>
        <h2>Learning how to use React Routers</h2>
      </div>
    </Router>
  );

Now we’re going to add a place where we put the different pages we want to display. Under the div but inside the Router, we’re going to add routes.

  </div>
  <Route path="/" component={Home} />
  <Route path="/about" component={About} />
</Router>

Now you’re probably getting little error lines on Home and About. That’s because we haven’t imported those pages yet. Underneath import react-router-dom, add this.

import Home from "./Components/Home";
import About from "./Components/About";

Note that your path may be different depending on what you named your folder or if you didn’t put them in a separate folder.

Test the Routes

Now let’s see what this looks like so far on the front-end. Cd to your folder and type npm start to see the site.

When it opens on localhost:3000, you should see your Home page. Based on the code above, it should look like this.

Now type in localhost:3000/about and you should see the About page.

But WAIT there’s an issue here. Why is it showing the Home AND About page?

Troubleshooting Routes

The Router paths that we added, <Route path="/" component={Home} /> <Route path="/about" component={About} />, look for the first path that matches. So when typing in /about, the first thing it reads is /, which matches Home’s path. It then continues reading /about and returns anything with about in its path. If we had a /about/me page, all three pages would would show up on that same page because it contains all the paths. /, /about, and /about/me. So how do we fix this? There’s 2 ways!

Option 1

Add exact in front of component like this.

<Route path="/" exact component={Home} />
<Route path="/about" exact component={About} />

This tells the Route to only show the path that matches exactly. Now test it on your localhost by refreshing localhost:3000/about. Only About should be showing now.

Option 2

Add a Switch component. In your import react-router-dom, add Switch.

import {Route, BrowserRouter as Router, Switch} from "react-router-dom";

Now wrap your Route path inside a Switch component.

<Switch> 
   <Route path="/" component={Home} />
   <Route path="/about" component={About} />
</Switch>

Test this by typing in localhost:3000/about. You notice Home is showing? That’s because Switch shows one item, like exact, but it shows the first matching result, unlike exact. So it read / and matched Home first before it could find /about. There’s 2 options to fix this.

Option 2.1

Keep exact in your Routes

<Switch> 
   <Route path="/" exact component={Home} />
   <Route path="/about" exact component={About} />
</Switch>
Option 2.2

Order them from longest to shortest so it checks the shortest one, /, last.

<Switch>
   <Route path="/about" component={About} />
   <Route path="/" component={Home} />
</Switch>

Let’s bring back that /about/me example. If that was in here, it would go:

<Switch>
   <Route path="/about/me" component={AboutMe} />
   <Route path="/about" component={About} />
   <Route path="/" component={Home} />
</Switch>

So if multiple options could pop up, and you don’t want multiple, put the shortest first.

You may be asking, what’s an example of needing Switch instead of just doing exact? If you wanted to get to /about/me but forgot the link and just typed in /me, Switch would send you to /about/me automatically because it’s the closest match. Exact would return an error because no path exactly matches /me.

Add Navigation

GREAT, we now see only what we want, so let’s add a navigation. Outside above the Switch component, add your nav.

<nav>
   <ul>
     <li>
        <Link to="/">Home</Link>
     </li>
     <li>
        <Link to="/about">About</Link>
     </li>
   </ul>
</nav>
<Switch>

In your import react-router-dom add the Link component.

import { Route, BrowserRouter as Router, Switch, Link } from "react-router-dom";

Why are we using Link instead of a href? Link will do client side routing and quickly switch pages without reloading anything, whereas a href will reload the entire page/application to get its anchor. That slows down user interaction.

Final Testing

Let’s go to localhost:3000 and see our application. You should be on the Home page and see a simple navigation.

Click Home and nothing should happen because, you’re on Home already. But when you click About, notice a very quick switch to the About page with no reload as it acts like a tab. Magical right?

Recap

If you need a recap, here’s the full code of our App.js

import React from "react";
import "./styles.css";
import { Route, BrowserRouter as Router, Switch, Link } from "react-router-dom";
import Home from "./Components/Home";
import About from "./Components/About";

export default function App() {
  return (
    <Router>
      <div className="App">
        <h1>React Routing</h1>
        <h2>Learning how to use React Routers</h2>
        <nav>
          <ul>
            <li>
              <Link to="/">Home</Link>
            </li>
            <li>
              <Link to="/about">About</Link>
            </li>
          </ul>
        </nav>
        <Switch>
          <Route path="/about" component={About} />
          <Route path="/" component={Home} />
        </Switch>
      </div>
    </Router>
  );
}

Click here for the Home and About code if you need some basic page examples.

Well there you have it! We’re all done. You now have a true single page application that replaces a href and never reloads.

Back to top

Hopefully this has helped someone to become 1 step closer to becoming a better developer.

Leave a Reply