DEV Community

Gabriel Bittencourt
Gabriel Bittencourt

Posted on

React router V6: Some of the new changes

ReactRouter
So not too long ago the library React Router has updated to version 6 and with that it came with some interesting changes that I notice and see people talking about, so I'm gonna describe some of them.

If you want to upgrade the version from 5 to 6 you can by seeing this link Upgrading React Router V5 to V6

First what is React Router?

React Router is a package for routing in React.js, as the documentation said "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."

So now that we know the basics of it, let's talk about some new changes it had.

Replacing Switch component with Routes

If you have ever used React Router you know that we need to wrap our routes into this Switch component that makes sure that only one of these routes is loaded at the same time, instead of all matching routes. Something like this

export function App() {
  return (
    <div>
      <Switch>
        <Route path="/about">
          <AboutPage />
        </Route>
        <Route exact path="/profile">
          <ProfilePage />
        </Route>
        <Route path="/profile/:id">
          <ProfileUserPage />
        </Route>
      </Switch>
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

Now with V6 we changed the name from Switch to Routes and now the Routes component has a new prop called element, where you pass the component it needs to render inside this component and be like this

export function App() {
  return (
    <div>
      <Routes>
        <Route path="/about" element={<AboutPage />} />
        <Route exact path="/profile" element={<ProfilePage />} />
        <Route path="/profile/:id" element={<ProfileUserPage />} />
      </Routes>
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

Internal changes & path evaluation (no more needed exact prop)

So with this new version some internal changes were made and the evaluation that React Router does for these paths and then picking a route to load changed. For V5 we needed to put the exact prop on the component to go for that specific route we want, like this in the Profile path below

export function App() {
  return (
    <div>
      <Routes>
        <Route path="/about" element={<AboutPage />} />
        <Route exact path="/profile" element={<ProfilePage />} />
        <Route path="/profile/:id" element={<ProfileUserPage />} />
      </Routes>
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

If we not put that exact prop it will render the path that starts with that path we pass and that's not what we wanted, now with V6 we don't need this prop anymore because React Router will always look for the exact path we pass, being like this

export function App() {
  return (
    <div>
      <Routes>
        <Route path="/about" element={<AboutPage />} />
        <Route path="/profile" element={<ProfilePage />} />
        <Route path="/profile/:id" element={<ProfileUserPage />} />
      </Routes>
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

Now let's talk about the Link component that we have, that still is on V6

NavLink activeClassName prop does not exists anymore

With that prop you could pass a class for that specific Link to be modified with some CSS to show that it's became active, like this

export function Header() {
  return (
    <header>
      <ul>
        <li>
          <NavLink activeClassName="active" to="/about" />
        </li>
        <li>
          <NavLink activeClassName="active" to="/profile" />
        </li>
      </ul>
    </header>
  )
}
Enter fullscreen mode Exit fullscreen mode

With V6 you have to manually do that and you can by passing a function to the className prop we have on React, like this

export function Header() {
  return (
    <header>
      <ul>
        <li>
          <NavLink className={(navData) => navData.isActive ? "active" : "" } to="/about" />
        </li>
        <li>
          <NavLink className={(navData) => navData.isActive ? "active" : "" } to="/profile" />
        </li>
      </ul>
    </header>
  )
}
Enter fullscreen mode Exit fullscreen mode

Note that the React Router provides you the navData argument and it's an object and inside has the isActive property that will be true if the route is active in that moment

The useParams hook

This hook from V5 has not changed from V6, you can still use it the same way, passing parameters to match a specific URL you're trying to match.

Well these are some of the changes React Router had, if you wanna see more of these changes you can see this video from Academind where he talks about it Here or by reading the documentation Here. I see you next time, thanks!

Discussion (14)

Collapse
sgarciadev profile image
Sergei Garcia • Edited on

Thanks for the article! As for feedback and anyone else reading this, you missed a lot of the more important, key, breaking changes React Router v6 introduced which you might want to double check. I think you focused a little too much on some of the less important ones (like NavLink's className prop)

  • The <Route> component has now deprecated its children & render props, so it's no longer possible to pass router props like history / location / match to components. You should now use the useNavigate / useLocation / useParams hooks.
  • The withRouter Higher Order Component which made it possible to get router props anywhere has also been deprecated in favor of React Hooks
  • The new <Routes> component that replaces <Switch> works entirely different now. It now will always focus on matching the most specific route instead of the first one it finds, making it more predictable.
  • Relative links work dramatically better and more predictably now.
  • Route patterns using Regexp are now deprecated, the only supported symbols are now : for dynamic routes (user/:id) and the * wildcard which can only be used at the end.

For anyone else curious to learn more about these v6 changes (and the reason behind them), I would strongly discourage any kind of video material such as the one linked from Academind linked, and instead recommend the official React Router v6 announcement blog post which does an incredibly great job explaining all the changes in a well explained, yet concise manner. As well as the reasons that drove the team to make them.

Collapse
not4ro profile image
Matteo Notaro

I'm trying it but there's one thing that hurts me...
I'm from Angular and i've noticed that you have to declare in one single place ALL the possible routes of the app (for nested routing you have to declare them inside a Route like this


<Route path={"father"} element={Father}>
<Route path={"child"} element={Child}/>
</Route>

It is possible to have a more "clean" way to declare the sub-path in the father component?

Collapse
gabrlcj profile image
Gabriel Bittencourt Author • Edited on

So you can attach at the end of the path of your father component a "/*", so react router will know that this route will only show if it starts with that path name and not the exact path name like this

<Routes>
  <Route path="/welcome/*" component={<Father />} />
</Routes>
Enter fullscreen mode Exit fullscreen mode

And then have other paths starting with the same path name but with some additional name at the end, so inside the father component you have it's child component and there you can put the nested route for that specific path name to render the child component like this

<Routes>
  <Route path="new-user" component={<Child />} />
</Routes>
Enter fullscreen mode Exit fullscreen mode

So you don't have to put all the routes in to the same file, and if they're nested routes you can just add the "/*" at the end of that path name and create a route inside the child component, so it loads when it match's the URL.

Collapse
not4ro profile image
Matteo Notaro

God bless you, ty

Collapse
miionu profile image
Rospars Quentin

I like the new Routes component instead of Switch, helps a lot to clarify the code :)

Collapse
gabrlcj profile image
Gabriel Bittencourt Author

Yeah me too, a much better understanding of the code!

Collapse
kona profile image
Bara Konateh

Yeah definitely helps with the readability, although I think switch made sense. Not a big fan of the activeClassName prop change though

Collapse
aliezeali profile image
Alieze-Ali

Great article, thanks!

Collapse
gabrlcj profile image
Gabriel Bittencourt Author

I'm glad you like it!!

Collapse
mridulbagla profile image
Mridul Bagla

Thanks :-)

Collapse
napster profile image
Marouane Etaraz

Thank you

Collapse
sm3dev profile image
Michael Wright, SMโ‚ƒ

Thanks for this and the links! ๐Ÿ™๐Ÿพ๐Ÿ™๐Ÿพ

Collapse
gabrlcj profile image
Gabriel Bittencourt Author

I'm glad you find useful!!!

Some comments have been hidden by the post's author - find out more