Skip to main content

Command Palette

Search for a command to run...

React Router v6 Latest Advances in Route Management

Updated
5 min read
React Router v6 Latest Advances in Route Management
T

I focus on the long-term foundations of computer science, software engineering, and emerging technologies.covering computer science, AI, semiconductors, quantum computing, and future engineering.

React Router v6 is a significant update for route management in React applications, introducing improvements and simplifications, including better handling of nested routes and enhanced use of hooks.

1. Routes Refactor

In v6, the <Route> component is wrapped within a <Routes> component, replacing the <Switch> component. <Routes> automatically renders the first matching route.

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

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="/users/*" element={<Users />} /> {/* Wildcard support */}
      </Routes>
    </Router>
  );
}

2. Using the element Property

Routes now specify the component to render using the element property, replacing component or render functions.

<Route path="/profile/:userId" element={<Profile />} />

3. Hook API

React Router v6 introduces hooks like useParams, useLocation, and useNavigate, enabling direct navigation handling within components.

import { useParams } from 'react-router-dom';

function Profile() {
  const { userId } = useParams();
  return <div>Profile of user {userId}</div>;
}

4. Navigate Function

The useNavigate hook returns a navigate function for programmatic navigation.

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

function ProfileForm() {
  const navigate = useNavigate();
  const handleSubmit = (event) => {
    event.preventDefault();
    // Navigate to another page after form submission
    navigate('/success', { replace: true }); // Replace current history entry
  };

  return <form onSubmit={handleSubmit}>...</form>;
}

5. Lazy Loading and Code Splitting

React Router v6 supports dynamic imports for code splitting, improving load times.

<Route path="/lazy" element={import('./LazyComponent').then((mod) => mod.LazyComponent)} />

6. 404 Page

Handle unmatched routes with a wildcard route to display a 404 page.

<Route path="*" element={<Error404 />} />

7. Nested Routes

Nested routes are simplified using <Routes> and <Route> combinations.

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/" element={<MainLayout />}>
          <Route index element={<Home />} />
          <Route path="about" element={<About />} />
          <Route path="users" element={<Users />}>
            <Route path=":userId" element={<User />} />
          </Route>
        </Route>
        <Route path="*" element={<Error404 />} />
      </Routes>
    </Router>
  );
}

8. Route Protection and Authorization

Use useEffect or useLayoutEffect with useNavigate to protect routes, ensuring only authenticated users access them.

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

function PrivateRoute({ children }) {
  const location = useLocation();
  const navigate = useNavigate();

  useEffect(() => {
    if (!isAuthenticated()) {
      navigate('/login', { replace: true });
    }
  }, [navigate]);

  return isAuthenticated() ? children : null;
}

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/" element={<PublicRoute><Home /></PublicRoute>} />
        <Route path="/dashboard" element={<PrivateRoute><Dashboard /></PrivateRoute>} />
        <Route path="/login" element={<Login />} />
      </Routes>
    </Router>
  );
}

Here, isAuthenticated() is a hypothetical function checking user authentication. Unauthenticated users are redirected to the login page.

9. Redirects and Navigation

The <Navigate> component facilitates redirects by triggering navigation to a specified URL.

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

function PrivateRoute({ children }) {
  if (!isAuthenticated()) {
    return <Navigate to="/login" replace />;
  }

  return children;
}

10. Route Parameters and Query Strings

Use useParams for route parameters and useLocation for query strings.

import { useParams, useLocation } from 'react-router-dom';

function Profile() {
  const { userId } = useParams();
  const query = new URLSearchParams(useLocation().search);
  const searchParam = query.get('paramName');

  return <div>Profile of user {userId} with search param: {searchParam}</div>;
}

11. Custom Route Matching

React Router v6 supports custom route matching via the path-to-regexp library, though standard path patterns are usually sufficient.

12. Higher-Order Components (HoCs)

While v6 discourages HoCs, you can still wrap components for specific logic, such as route protection.

function PrivateRoute({ children }) {
  if (!isAuthenticated()) {
    return <Navigate to="/login" replace />;
  }

  return <>{children}</>;
}

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/" element={<PublicRoute><Home /></PublicRoute>} />
        <Route path="/dashboard" element={<PrivateRoute><Dashboard /></PrivateRoute>} />
        <Route path="/login" element={<Login />} />
      </Routes>
    </Router>
  );
}

13. Route Events

React Router v6 provides lifecycle hooks like useLocation and useNavigate to monitor and respond to route changes.

import { useLocation } from 'react-router-dom';

function Navbar() {
  const location = useLocation();

  useEffect(() => {
    console.log(`Navigated to ${location.pathname}`);
  }, [location]);

  return /* ... */;
}

14. Modular Route Configuration

Keep code clean by splitting route configurations into modules and merging them in the main configuration.

// routes/users.js
export default [
  { path: '/users', element: <UsersList /> },
  { path: '/users/:id', element: <UserProfile /> },
];

// routes/admin.js
export default [
  { path: '/admin/dashboard', element: <AdminDashboard /> },
  { path: '/admin/users', element: <AdminUsers /> },
];

// App.js
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import usersRoutes from './routes/users';
import adminRoutes from './routes/admin';

function App() {
  return (
    <Router>
      <Routes>
        {usersRoutes.map((route, index) => (
          <Route key={index} {...route} />
        ))}
        {adminRoutes.map((route, index) => (
          <Route key={index} {...route} />
        ))}
        <Route path="*" element={<ErrorPage />} />
      </Routes>
    </Router>
  );
}

15. Route Guards

Create custom guard functions to control route access, often for authorization or data preloading.

function requireAuth(nextState, replace) {
  if (!isAuthenticated()) {
    replace({
      pathname: '/login',
      state: { nextPathname: nextState.location.pathname },
    });
  }
}

// In routes
<Route path="/protected" onEnter={requireAuth} element={<ProtectedComponent />} />

In v6, use useEffect or useLayoutEffect for similar functionality.

16. Nested Routing

Nested routes are handled without explicitly wrapping <Switch>, using nested <Routes>:

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/" element={<MainLayout />}>
          <Route index element={<Home />} />
          <Route path="about" element={<About />} />
          <Route path="users" element={<Users />}>
            <Route path=":userId" element={<User />} />
          </Route>
        </Route>
        <Route path="*" element={<Error404 />} />
      </Routes>
    </Router>
  );
}

Here, /users/:userId is defined within /users, rendering both Users and User components for /users/someId.

17. Custom Error Handling

React Router v6 doesn’t provide global error handling, but you can use window.onerror or custom middleware.

18. Code Splitting and Lazy Loading

React Router v6 integrates with Webpack or other bundlers for code splitting and lazy loading using dynamic import():

<Route
  path="/lazy"
  element={
    import('./LazyComponent')
      .then((mod) => mod.LazyComponent)
      .catch((error) => <ErrorBoundary error={error} />)
  }
/>

19. Custom Route Components

While the <Route> component is simplified, you can create custom components to extend functionality, such as adding loading indicators.

20. Server-Side Rendering (SSR)

React Router v6 supports SSR with additional configuration and libraries like react-router-dom/server and react-router-dom/browser.

Web Development

Part 11 of 46

The content covers the three basics of HTML/CSS/JS/TS, modular development, mainstream frameworks (Vue, React, Angular, Svelte), build tools, browser plug-in development, Node.js backend practice, Next.js/Nest.js and other popular technologies.

Up next

SvelteKit A New Framework for Building High-Performance SSR Applications

SvelteKit is a next-generation framework based on Svelte, designed for building server-side rendered (SSR) and static site generated (SSG) applications. Svelte is a lightweight frontend framework known for its exceptional performance and concise code...

More from this blog

T

Tianya School Technical Articles

48 posts

Welcome to our tech publication, where we share high-quality content on full-stack development, frontend/backend/web3/AI, and engineering best practices.