DEV Community

Cover image for React Router V5 vs V6
Arunava Modak
Arunava Modak

Posted on

React Router V5 vs V6

React Router version 6 was released recently, and it is important for us to understand the changes as it is one of the most widely used react libraries out there.

So What Is React Router ?

React Router is a fully-featured client and server-side routing library for React, a JavaScript library for building user interfaces. React Router runs anywhere React runs; on the web, on the server with node.js, and on React Native.

In V6, there has been a lot of under the hood changes, be it an enhanced path pattern matching algorithm or addition of new components. Not only that but the bundle size has been reduced by almost 58%.

Wow

So here are some of the changes you can make to upgrade an existing project from React Router v5 to v6.

Switch Replaced With Routes

In v6, Switch in not exported from react-router-dom. In the earlier version we could use Switch to wrap our routes. Now we use Routes to do the same thing instead of Switch.

Changes In The Way We Define Our Route

The component that should be rendered on matching a route can not be written as children of the Route component, but it takes a prop called element where we have to pass a JSX component for that to be rendered.

The exact Prop Is Not Needed Anymore

With version 6, React Router has just become alot more awesome. The now better, path matching algorithm, enables us to match a particular route match without the exact prop. Earlier, without exact, any URL starting with the concerned keyword would be loaded, as the matching process was done from top to down the route definitions. But now, we do not have to worry about that, as React Router has a better algorithm for loading the best route for a particular URL, the order of defining does not really matters now.

So, to sum up these three points we can consider this code snippet.

In v5

import { Switch, Route } from "react-router-dom";
.
.
.
<Switch>
    <Route path="/">
        <Home/>
    </Route>
    <Route exact path="/cryptocurrencies">
        <Cryptocurrencies/>
    </Route>
    <Route exact path="/crypto/:coinId">
        <CryptoDetails/>
    </Route>
    <Route exact path="/exchanges">
        <Exchanges />
    </Route>
</Switch>
Enter fullscreen mode Exit fullscreen mode

In v6

import { Routes, Route } from "react-router-dom";
.
.
.
<Routes>
   <Route path="/" element={<Home />} />
   <Route path="/crypto/:coinId" element={<CryptoDetails />} />
   <Route path="/cryptocurrencies" element={<Cryptocurrencies />} />

   <Route path="/exchanges" element={<Exchanges />} />
</Routes>
Enter fullscreen mode Exit fullscreen mode

No Need To Install react-router-config Seperately

react-router-config allowed us to define our routes as javascript objects, instead of React elements, and all it's functionalities have to moved in the core react router v6.

//V5
import { renderRoutes } from "react-router-config";

const routes = [
  {
    path: "/",
    exact: true,
    component: Home
  },
  {
    path: "/cryptocurrencies",
    exact: true,
    component: Cryptocurrencies
  },
  {
    path: "/exchanges",
    exact: true,
    component: Exchanges
  }
];

export default function App() {
   return (
     <div>
       <Router>{renderRoutes(routes)}</Router>
     </div>
   );
}




//V6
function App() {
  let element = useRoutes([
    // These are the same as the props you provide to <Route>
    { path: "/", element: <Home /> },
    { path: "/cryptocurrencies", element: <Cryptocurrencies />,
      // Nested routes use a children property
      children: [
        { path: ":coinId", element: <CryptoDetails /> },
      ] 
    },
    {
      path: "/exchanges",
      element: <Exchanges />
    },
  ]);

  // The returned element will render the entire element
  // hierarchy with all the appropriate context it needs
  return element;
}
Enter fullscreen mode Exit fullscreen mode

useHistory Is Now useNavigate

React Router v6 now has the navigate api, which most of the times would mean replacing useHistory to useNavigate.


//V5
import { useHistory } from "react-router-dom";

function News() {
  let history = useHistory();
  function handleClick() {
    history.push("/home");
  }
  return (
    <div>
      <button onClick={()=>{
           history.push("/home");
      }}>Home</button>
    </div>
  );
}


//V6
import { useNavigate } from "react-router-dom";

function News() {
  let navigate = useNavigate();

  return (
    <div>
      <button onClick={()=>{
          navigate("/home");
      }}>go home</button>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

Some more common features of useHistory were go, goBack and goForward. These can also be achieved by navigate api too, we just need to mention the number of steps we want to move forward or backward ('+' for forward and '-' for backward). So we can code these features we can consider this.

//V5
import { useHistory } from "react-router-dom";

function Exchanges() {
  const { go, goBack, goForward } = useHistory();

  return (
    <>
      <button onClick={() => go(-2)}>
        2 steps back
      </button>
      <button onClick={goBack}>1 step back</button>
      <button onClick={goForward}>1 step forward</button>
      <button onClick={() => go(2)}>
        2 steps forward
      </button>
    </>
  );
}


//V6
import { useNavigate } from "react-router-dom";

function Exchanges() {
  const navigate = useNavigate();

  return (
    <>
      <button onClick={() => navigate(-2)}>
        2 steps back
      </button>
      <button onClick={() => navigate(-1)}>1 step back</button>
      <button onClick={() => navigate(1)}>
        1 step forward
      </button>
      <button onClick={() => navigate(2)}>
        2 steps forward
      </button>
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

activeStyle and activeClassName Props Removed From <NavLink />

In the previous version we could set a seperate class or a style object for the time when the <NavLink/> would be active. In V6, these two props are removed, instead in case of Nav Links className and style props, work a bit differently. They take a function which in turn gives up some information about the link, for us to better control the styles.

//V5
<NavLink
  to="/news"
  style={{ color: 'black' }}
  activeStyle={{ color: 'blue' }}>
  Exchanges
</NavLink>

<NavLink
  to="/news"
  className="nav-link"
  activeClassName="active">
  Exchanges
</NavLink>

//V6
<NavLink
  to="/news"
  style={({isActive}) => { color: isActive ? 'blue' : 'black' }}>
  Exchanges
</NavLink>

<NavLink
  to="/news"
  className={({ isActive }) => "nav-link" + (isActive ? "active" : "")}>
  Exchanges
</NavLink>
Enter fullscreen mode Exit fullscreen mode

Replace Redirect with Navigate

Redirect is no longer exported from react-router-dom, instead we use can Navigate to achieve the same features.

//V5
import { Redirect } from "react-router-dom";

<Route exact path="/latest-news">
    <Redirect to="/news">
</Route>
<Route exact path="/news">
    <News />
</Route>


//V6
import { Navigate } from "react-router-dom";

<Route path="/latest-news" element={<Navigate replace to="/news">} />
<Route path="/news" element={<Home />} />
Enter fullscreen mode Exit fullscreen mode

Please note the replace prop passed inside the element of the Route. This signifies we are replacing the current navigation stack. Without replace it would mean we are just pushing the component in the existing navigation stack.

That's it for today. Hope this helps you upgrading your react project, to React Router V6.

Thank you for reading !! 😇😇
Happy Coding !! Happy Building !!

Discussion (12)

Collapse
henrikvtcodes profile image
Henrik VT

As someone who hasn't used React Router, what's the advantage of using this over a framework like Next.js or Gatsby?

Collapse
arunavamodak profile image
Arunava Modak Author

Well it totally depends on the requirement of your project.
If you want an SPA, you can use React and React Router, which takes care of your client-side routing. For something like Next.js it comes with it's own page based routing, I don't think we can implement SPA.

Collapse
johannesmogashoa profile image
Johannes Mogashoa

React Router is directly plugged into Next without you having to install it as a separate dependency. For instance, with Next when you add a new JS/TS or JSX/TSX file into the pages folder, it will automatically map out the path for you without you having to define it.

Collapse
lesleyvdp profile image
Lesley van der Pol

I don't think there is an advantage of using React Router over Next.js or Gatsby. If you want the tools that Next or Gatsby offer then it makes sense to just go for those. If you're working on a more vanilla React project then you will generally see something like React Router in place to handle the routing.

Collapse
multiwebinc profile image
Mike Robinson

Next and Gatsby are full-fledged frameworks and do a LOT more than just routing. If you're already using them, there's no need to use React Router.

Collapse
swastikyadav profile image
Swastik Yadav

Hey Arunava, Thanks for such nice and detailed explanation about the changes in react-router v6.

Collapse
arunavamodak profile image
Arunava Modak Author

Thanks man. Just looking to contribute something to the community

Collapse
ferdiansyah0611 profile image
Ferdiansyah

nice👏

Collapse
rancy98 profile image
rancy98

quality sharing!

Collapse
th3c0r profile image
th3c0r

Very nice article! Also a good video tutorial from Academind youtu.be/zEQiNFAwDGo

Collapse
multiwebinc profile image
Mike Robinson

There's also an official upgrading guide: github.com/remix-run/react-router/...

Collapse
kpervin profile image
Kristofer Pervin • Edited on

At some point can you add in built-in Protected Routes? It would be quite the convenience feature. Otherwise this looks great!