6 Cool new features in React Router 6

6 Cool new features in React Router 6

React router 6 comes with first class suspense support, many new features and many enhancements. Let's looks at those case by case.

1. Welcome new Routes component

In this version, Switch component is replaced by Routes component, to support the branch new feature named relative routing.

function App() {
   return (
     <BrowserRouter>
         <Routes> // Replace Switch with Routes
            <Route path="/Home">
              <Home />
            </Route>
            <Route path="/user">
               <Users />
            </Route>
         </Routes>
     </BrowserRouter>
   )
}

2. Truely Relative Routes

When we write nested route, here after we don't need to specify full complete route path by combining the current route's path + new route slug.

// In v5 we used to do like this

function App() {
   return (
     <BrowserRouter>
         <Route path="/user">
            <Users />
         </Route>
     </BrowserRouter>
   )
}

function Users() {
  let match = useRouteMatch();

  return (
    <div>
      <nav>
        <Link to={`${match.url}/me`}>My Profile</Link>
      </nav>

      <Switch>
        <Route path={`${match.path}/me`}>
          <OwnUserProfile />
        </Route>
        <Route path={`${match.path}/:id`}>
          <UserProfile />
        </Route>
      </Switch>
    </div>
  );
}
//  v6
function App() {
   return (
     <BrowserRouter>
         <Route path="/user/*">
            <Users />
         </Route>
     </BrowserRouter>
   )
}

function Users() {
  let match = useRouteMatch();

  return (
    <div>
      <nav>
        <Link to={`me`}>My Profile</Link>
      </nav>

      // We used <Routes> instead of <Switch>, which is new replacement.
      <Routes> 
        <Route path={`me`}>
          <OwnUserProfile />
        </Route>
        <Route path={`:id`}>
          <UserProfile />
        </Route>
      </Routes>
    </div>
  );
}

Did you observed the <Route path={me}>, this is the huge win, now we no longer need to construct the full path, which tedious. Also did you noticed * here <Route path="/user/*"> . * hints the React Router that this Routes contains Sub-routes. With that followings are all valid path pattern

/groups
/groups/admin
/users/:id
/users/:id/messages
/files/*
/files/:id/*
/files-*

3. More powerful Navigation

Goodbye History API and welcome Navigation API. Yes, In V6, we have new apis and hooks for better navigation.

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

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

Also we can leverage the same relative routing advantages in navigate apis too

import { Routes, Route, useNavigate } from "react-router-dom";

function App() {
  let navigate = useNavigate();
  function handleClick() {
    navigate("/home");
  }
  return (
    <Routes>
      <Route element={<Home />} path="/home">
    </Routes>
  );
}

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

  const onClick = () => {
    // this will navigate to the /home/dashboard
    navigate("dashboard", { state: { report: "pivot" }, replace: true })
  };

  return (
      <button onClick={onClick}>
          Dashboard
      </button>
  );
}

We have new ways of doing history.goBack, history.goForward with new navigation

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

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

  return (
    <>
      <button onClick={() => navigate(-2)}>Go 2 pages back</button>
      <button onClick={() => navigate(-1)}>Go back</button>
      <button onClick={() => navigate(1)}>Go forward</button>
      <button onClick={() => navigate(2)}>Go 2 pages forward</button>
    </>
  );
}

With a new navigation, Redirect component is replaced with new Navigate component.

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

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

4. New Outlet component

To bring all the routes to one place and give nicer way to nest them, v6 has brought back the Outlet component. <Route children /> way of defining the routes provides us a way to cleanly specify the nested routes of a module or sub modules of our app.

// This is a React Router v6 app
import { BrowserRouter, Routes, Route, Link, Outlet } from "react-router-dom";

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="users" element={<Users />}>
          <Route path="me" element={<OwnUserProfile />} />
          <Route path=":id" element={<UserProfile />} />
        </Route>
      </Routes>
    </BrowserRouter>
  );
}

function Users() {
  return (
    <div>
      <nav>
        <Link to="me">My Profile</Link>
      </nav>
      // Children of users route will be rendered here when visiting /users/me or /users/id
      <Outlet />
    </div>
  );
}

We have nested Route inside Route, this is cool way of defining all the child routes of a component in one place and we render them using <Outlet /> component.

5. New useRoutes hook

With this hook we can create our routes definition using json object instead with components.

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 /> }
      ]
    },
    // 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;
}

activeClassNamve and activeStyle props are removed in favour of this feature.

<NavLink
  to="/messages"
  className={({ isActive }) => "nav-link" + (isActive ? " activated" : "")}
>
  Messages
</NavLink>

<NavLink
  to="/messages"
  style={({ isActive }) => ({ color: isActive ? 'green' : 'blue })}
>
  Messages
</NavLink>

React Router v6 brings more enhancements along with these main features, for more info refer here