Type-Safe Routing in React with React Router and TypeScript

Overview

React Router is a popular library for handling navigation in React applications. It can be combined with TypeScript to provide a type-safe routing experience, reducing runtime errors. Using React Router with TypeScript, we will demonstrate how type-safe routing can be implemented in React.

If you are new to React TypeScript or still learning about it, I recommend you read my article "How to Get Started with React TypeScript".

Installing Dependencies

We will start by installing the required packages.

npm install react-router-dom @types/react-router-dom

Creating Routes with TypeScript

To encapsulate our routes, we will use the Route component from the React Router. Below is an example of how to create a Routes component.

// App.tsx
import React, { useState } from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import Navigation from './Components/Navigation';
import RedirectToHome from './Components/RedirectToHome';
import Home from './Screens/Home';  
import About from './Screens/About';
import Contact from './Screens/Contact';
import UserProfile from './Screens/UserProfile';

const App: React.FC = () => {
  
  return (
    <Router>
      <div>
        <Navigation />
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/about" element={<About />} />
          <Route path="/contact" element={<Contact />} />
          <Route path="/redirect" element={<RedirectToHome />} />
          <Route path="/userprofile/:username" element={<UserProfile />} />       
   
        </Routes>
      </div>
    </Router>
  );
};

export default App;

Navigating Between Routes

In order to ensure type safety, we will be using the Link component to create links between routes.

//Simple way to Navigate Between Routes with TypeScript
import React from 'react';
import { Link } from 'react-router-dom';

const Navigation: React.FC = () => {
    let username = 'JoeBlog';
  return (
    (<nav>
      <ul>
        <li>
          <Link to="/">Home</Link>
              </li>
              <li>
         <Link to="/redirect">Redirect To Home</Link>
        </li>
        <li>
          <Link to="/about">About</Link>
        </li>
        <li>
          <Link to="/contact">Contact</Link>
        </li>
        <li>
                  <Link to={`/userprofile/${username}`}>User Profile</Link>
        </li>
      </ul>
    </nav>)
  );
};

export default Navigation;

Accessing Route Parameters

To access parameters type-safely when using routes involving parameters, use the useParams hook.

// Accessing Route Parameters with TypeScript in React
 import React from 'react';
import { useParams } from 'react-router-dom';

interface UserProfileParams {
  username: string;
  [key: string]: string | undefined;
}

const UserProfile: React.FC = () => {
  const { username } = useParams<UserProfileParams>();

  return (
    <div>
      <h1>User Profile Example</h1>
      <p>This is the User Profile page content.</p>
      <h2>{`Username: ${username}`}</h2>
    </div>
  );
};

export default UserProfile;

Redirecting Between Routes

 Using TypeScript and Navigate, implement route redirection.

// Redirecting Between Routes with TypeScript in React
import React, { useEffect, useState } from 'react';
import { Navigate } from 'react-router-dom';

const RedirectToHome: React.FC = () => {
  const [redirecting, setRedirecting] = useState(true);

  useEffect(() => {
    const timer = setTimeout(() => {
      setRedirecting(false);
    }, 4000);

    return () => clearTimeout(timer);
  }, []);

  return (
    <div>
      {redirecting ? (
        <p>Redirecting to Home...</p>
      ) : (
        <Navigate to="/" />
      )}
    </div>
  );
};

export default RedirectToHome;

Guarding Routes

 The Route component's element prop can be used with TypeScript to ensure type safety when guarding routes based on conditions.

// ProtectedComponent 
import React from 'react';

const ProtectedComponent: React.FC = () => {
  return (
    <div>
      <h2>Protected Component</h2>
      <p>This is a protected component.</p>
    </div>
  );
};

export default ProtectedComponent;
// Guarding Routes with TypeScript in React
 import React from 'react';
import { Route, Navigate } from 'react-router-dom';
import ProtectedComponent from './ProtectedComponent'; 

interface PrivateRouteProps {
  element: React.ReactNode;
  isAuthenticated: boolean;
  path?: string;  
}

const PrivateRoute: React.FC<PrivateRouteProps> = ({ element, isAuthenticated, ...rest }) => {
  return isAuthenticated ? (
    <Route {...rest} element={<ProtectedComponent />} />
  ) : (
    <Navigate to="/login" replace />
  );
};

export default PrivateRoute;

Summary

In our React applications, we can create type-safe routing by combining React Router and TypeScript. By catching errors at compile-time, this enhances the development process and results in a more robust and maintainable code. Customize Our routing experience by experimenting with different route configurations, accessing route parameters, and adding features like route guards. I’ve added the source code for this article on the following GitHub Repository   https://github.com/ziggyrafiq/React-TypeSafe-Routing-with-React-Router-and-TypeScript and please do not forget to follow me on LinkedIn. My LinkedIn profile is https://www.linkedin.com/in/ziggyrafiq/


Capgemini
Capgemini is a global leader in consulting, technology services, and digital transformation.