React Router v6 is both the next version of React Router v5 but also @reach/router… it’s a coming together of all the best things from both routers in an easy to use light-weight package. In this tutorial we’ll cover all the basics from routing, nested routes, dynamic routes, linking to catch-all routes in just over 15 minutes.

Learn what’s coming in the latest alpha

At the time of this writing, React Router v6 is still in alpha, but the time is about right to start playing with it and exploring what’s to come. This guide will give you a peek at the new features/changes!

As you may already know, there is another great routing solution for React called Reach Router. Reach Router is lightweight, easier to use, and focuses on accessibility. React Router and Reach Router will be merged together and React Router is going to be the surviving project.

We’ve seen the first efforts in v5.1 with Hooks API, but we’re starting to see the actual results with v6: nested routes, relative links, relative routes, automatic route ranking, and so on.

Note: React Router v6.0.0-alpha.2 was used at the time of writing.

Get React Router v6

Run the following command to get React Router v6:

npm install react-router@next react-router-dom@next

Bundle Size

One of the great improvements over previous versions is the bundle size. It has been reduced by almost 70% from the previous version.
React Router v6

Switch to Routes

<Switch> is replaced with <Routes>. Thanks to this new API, we can define all our routes in one place and have automatic route ranking as well as relative routes and links.

import React from 'react';
import ReactDOM from 'react-dom';
import {
  BrowserRouter as Router,
  Routes,
  Route
} from 'react-router-dom';

function App() {
  return (
    <div>
      <h1>Welcome</h1>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="about" element={<About />} />
      </Routes>
    </div>
  );
}

ReactDOM.render((
  <Router>
    <App />
  </Router>
), document.getElementById('app'));

Nested and Relative Routes With Automatic Route Matching

<Route> has undergone some changes to make our lives easier.

  • <Route component> was removed in favor of <Route element>.
  • <Route children> was changed to accept child routes.
  • No more <Route exact> and <Route strict> since routes are matched automatically.
  • <Route path> is relative to the route’s hierarchy.
import { Routes, Route, Outlet } from 'react-router-dom';

function Invoices() {
  return (
    <div>
      <h1>Invoices</h1>

      {/*
        This element renders the element for the child route, which in
        this case will be either <SentInvoices> or <IndividualInvoice>
      */}
      <Outlet />
    </div>
  );
}

function IndividualInvoice() {
  let { invoiceId } = useParams();
  return <h1>Invoice {invoiceId}</h1>;
}

function SentInvoices() {
  return <h1>Sent Invoices</h1>;
}

function App() {
  return (
    <Routes>
      <Route path="invoices" element={<Invoices />}>
        <Route path=":invoiceId" element={<IndividualInvoice />} />
        <Route path="sent" element={<SentInvoices />} />
      </Route>
    </Routes>
  );
}

Relative Links

Just like <Route path>, <Link to> is also relative to the route’s hierarchy. If you omit the beginning /, it becomes relative to the route path that it sits in.

import { Routes, Route, Link, Outlet } from 'react-router-dom';

function Home() {
  return <h1>Home</h1>;
}

function Dashboard() {
  return (
    <div>
      <h1>Dashboard</h1>
      <nav>
        <Link to="invoices">Invoices</Link>{" "}
        <Link to="team">Team</Link>
      </nav>
      <hr />
      <Outlet />
    </div>
  );
}

function Invoices() {
  return <h1>Invoices</h1>;
}

function Team() {
  return <h1>Team</h1>;
}

function App() {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="dashboard" element={<Dashboard />}>
        <Route path="invoices" element={<Invoices />} />
        <Route path="team" element={<Team />} />
      </Route>
    </Routes>
  );
}

Descendant Routes

You have the freedom to use multiple <Routes> in one application. It can be useful to compose small applications to work together.

import React from 'react';
import { Routes, Route } from 'react-router-dom';

function Dashboard() {
  return (
    <div>
      <p>Look, more routes!</p>
      <Routes>
        <Route path="/" element={<DashboardGraphs />} />
        <Route path="invoices" element={<InvoiceList />} />
      </Routes>
    </div>
  );
}

function App() {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="dashboard/*" element={<Dashboard />} />
    </Routes>
  );
}

useRoutes

Do you remember the react-router-config package that enabled you to define your routes as an object? Well, that package is history. Now we havethe useRoutes hook instead.

It’s similar to the old package with a few improvements. You define your routes as an array of objects, pass it to the custom hook, and you get a React element that you can render. That’s it.

Here is an example configuration:

function App() {
  let element = useRoutes([
    // These are the same as the props you provide to <Route>
    { path: '/', element: <Home /> },
    { path: 'dashboard', element: <Dashboard /> },
    { path: 'invoices',
      element: <Invoices />,
      // Nested routes use a children property, which is also
      // the same as <Route>
      children: [
        { path: ':id', element: <Invoice /> },
        { path: 'sent', element: <SentInvoices /> }
      ]
    },
    // Redirects use a redirectTo property to
    { path: 'home', redirectTo: '/' },
    // Not found routes work as you'd expect
    { path: '*', element: <NotFound /> }
  ]);

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

I hope it’s not going to be a surprise for you if I say <Routes> is just a wrapper component over useRoutes.

useNavigate Instead of useHistory

useHistory is now history. It’s been replaced with React’s suspense-ready navigate API. From now on, you can useNavigate to navigate around. It has both imperative and declarative options.

import { Navigate, useNavigate } from 'react-router-dom';

function Declarative() {
  return <Navigate to="/home" replace state={state} />;
}

function Imperative() {
  let navigate = useNavigate();
  function handleClick() {
    navigate('/home')
  }
  return (
    <div>
      <button onClick={handleClick}>go home</button>
    </div>
  );
}

Conclusion

More and more details will surely come in the following days. No matter what, I’m already happy with what I see.

Happy coding!

Source code: https://github.com/leighhalliday/react-router-v6-demo
Getting started guide: https://github.com/ReactTraining/react-router/blob/dev/docs/installation/getting-started.md

#reactjs #webdev #javascript

React Router v6 Tutorial
146.40 GEEK