DEV Community

Cover image for Quick Guide to React Router 6.0 (Beta)
Mike Conner
Mike Conner

Posted on • Edited on

Quick Guide to React Router 6.0 (Beta)

React is one of the most commonly-used frameworks for designing webpages. However, it still has its flaws. One of these flaws is the lack of a built-in router. Enter React Router! As stated on their website, React Router is a collection of navigational components that allow you to compose declaratively within your application. For example, if you want to create a single-page application, but plan to incorporate multiple views, React Router will allow you to render those views without the need to refresh the entire page. Lets take a look at such an implementation using React Router version 6.0 (currently in beta).

Setup

The easiest way to start building a react app is to use the 'npx create-react-app' command from your terminal, so we'll assume you've done just that. From there, navigate into the root folder of your app and install react-router@next and react-router-dom@next. After that, navigate to the src/App.js file and add the following to the list of imports at the top of the page:

import { 
  BrowserRouter as 
    Router, 
    Routes, 
    Route, 
    Link, 
    Outlet, 
    useParams,
  } from 'react-router-dom';
Enter fullscreen mode Exit fullscreen mode

As to what each of these does, I'll explain as we use them. From here, we're ready to start coding!

Getting Started

To begin, we'll render a React component inside of an element with the "Router" designation that we imported earlier. That should look something like this:

function App() {
  return (
    <Router>
      Hello!
    </Router>
  );
}
Enter fullscreen mode Exit fullscreen mode

All of our routes will be declared in-between those two Router tags, which unsurprisingly handles the routing. Each individual route will be described using the "Route" tag, and stored in a component given the "Routes" tag. To that effect, "Routes" functions as the "Switch" component of older versions of React Router, providing relative routing and linking, automatic route ranking, and nested routes, while "Route" is responsible for actually rendering the UI of a given component. This will make a little more sense if we actually create a route and put it in its routes home, so lets go ahead and do that. Please bear in mind that everything we create from here on out will be either contained within the App function we created above or a modification of the return call of that same function:

const Home = () => {
  return (
    <div>
      <h1>
        Welcome Home!
      </h1>
      <p>This is where you live!</p>
    </div>
  )
};

return (
    <Router>
      <Routes>
        <Route path="/" element={<Home />} />
      </Routes>
    </Router>
  );
Enter fullscreen mode Exit fullscreen mode

So here you can see that we have created a component that we would like to display, Home. We have used the Route element with a path property to declare that when there is nothing else in the address bar following our default URL, we would like to render Home. And we have placed that Route in our list of Routes. Lets add another component so that we can see our routes in action:

const Whales = () => {
  return (
    <div>
      <h2>
        Whale Facts:
      </h2>
      <p>Whales are large mammals. Neat!</p>
    </div>
  )
};

return (
    <Router>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/whales" element={<Whales />} />
      </Routes>
    </Router>
  );
Enter fullscreen mode Exit fullscreen mode

After this, we have two possible routes. Assuming you haven't changed anything else, when you run "npm start" in the terminal, you should be directed to localhost:8000 and see something like this:
Alt Text
And if you navigate to the url localhost:8000/whales, you should see:
Alt Text
So this is pretty cool, but how are people supposed to know that they need to navigate to /whales to view your awesome whale info? The answer is they aren't, we'll use that Link variable that we imported earlier to send them there!

Link

Link allows you to navigate to a different view without having to refresh your page. We can use link to make a nav bar and switch between our different views using something similar to hyperlinks and buttons. Lets modify our code to accomplish this:

return (
    <Router>
      <nav>
        <Link
          to="/"
          style={{ padding: 10 }}
        >
          Home
        </Link>
        <Link
          to="whales"
          style={{padding: 10}}
        >
          Whales!
        </Link>
      </nav>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/whales" element={<Whales />} />
      </Routes>
    </Router>
  );
Enter fullscreen mode Exit fullscreen mode

All we've done here is declare a nav element and add two links to it, the first of which (Home) will link to the path specified by '/' and the second of which (Whales!) will link to the path specified by "whales". Our home page now looks something like this:
Alt Text
Clicking the two links will change to the appropriate view. Neat! But theres still one more powerful tool I'd like to talk about and that is....

Nested Routes

A nested route occurs when one part of the webpage stays the same while some child component of the page changes. We use the Outlet parameter we imported to accomplish this. Lets do a little bit of set-up before we dive in. First we'll code out some information that we'd like to render:

const PorcupineFacts = [
  {
    num: 0,
    type: 'Old-world porcupines',
    desc: 'These are porcupines!'
  },
  {
    num: 1,
    type: 'New-world porcupines',
    desc: 'These are ALSO porcupines!'
  }
];
Enter fullscreen mode Exit fullscreen mode

Next, we'll add a "parent component" that will allow you to select certain parts of our information to display:

const Porcupines = () => {
  return (
    <div>
      <h2>
        Porcupines
      </h2>
      <Outlet />
    </div>
  )
};
Enter fullscreen mode Exit fullscreen mode

Notice that we have placed our Outlet element here. Any matching child components will be rendered in place of the outlet tag. So lets make our child component next, and we'll follow that with the final update to our render:

const PorcupineList = () => {
  return (
    <ul>
      {PorcupineFacts.map((porc) => (
        <li key={porc.num}>
          <Link to={`/porcupines/${porc.type}`}>
            {porc.type}
          </Link>
        </li>
      ))}
    </ul>
  )
}

const Facts = () => {
  const { porcs } = useParams();
  const info = PorcupineFacts.filter(porcupine => porcupine.type === porcs)[0];
  return (
    <div>
      <h3>{info.type}</h3>
      <p>{info.desc}</p>
    </div>
  );
}

return (
  <Router>
    <nav>
      <Link
        to="/"
        style={{ padding: 10 }}
      >
        Home
      </Link>
      <Link
        to="whales"
        style={{padding: 10}}
      >
        Whales!
      </Link>
      <Link
        to="porcupines"
        style={{padding: 10}}
      >
        Porcupines
      </Link>
    </nav>
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/whales" element={<Whales />} />
      <Route path="porcupines" element={<Porcupines />} >
        <Route path="/" element={<PorcupineList />} />
        <Route path=":porcs" element={<Facts />} />
      </Route>
    </Routes>
  </Router>
);
Enter fullscreen mode Exit fullscreen mode

Ok, so lets talk about what just happened. We created a child element that will render once for every item in our data list (notice the .map?). Every time it renders, it will itself make a new Link based on the type property of each data entry. Notice that that link is preceded by /porcupines/, which is what we've called the path in our list of routes. In our final new route (:porcs), we have made a render call to the last component we created, Facts. Facts uses useParams() to grab the parameters we pass it in the Link tag, in this case porc.type. We use that parameter to find the appropriate info in our data object, and render that info in. And in our routes, we've nested both Routes inside of the overarching porcupines Route. We've also added a convenient Porcupine link to our navbar! So lets review. Our home page now looks like:
Alt Text
Lets click on porcupine to see our Porcupines component rendered, as well as one rendering of our PorcupineList component for each object in our data.
Alt Text
Finally, lets click on Old-world porcupines to see our link in action and our facts component rendered, all without a single page refresh:
Alt Text

Conclusion

React Router is a great way to give you more control over page navigation and page refreshes. It addresses one of vanilla Reacts weaknesses, lack of a built-in router.

Top comments (0)