How to Create a Protected Route with react-router-dom?

If you are working with ReactJS and using react-router-dom for routing, you may encounter the need to create a protected route. A protected route ensures that only authenticated users can access certain pages or components within your application.

Why Create a Protected Route?

Creating a protected route is essential for security and authorization purposes. For example, if your application has a dashboard page that should only be accessible to authenticated users, you can implement a protected route to restrict unauthorized access.

Using react-router-dom to Create Protected Routes

To create a protected route with react-router-dom, you can leverage the Route component provided by the library. Here's a step-by-step guide on how to do it:

Step 1: Set Up Context

In this example, we will be using Context API for authentication. Start by creating a new file called context.js and defining the necessary context and provider components:

            
import React, { Component, createContext } from "react";
import axios from "axios";

export const AuthContext = createContext();

export class AuthProvider extends Component {
  state = {
    isAuthenticated: false,
    user: null,
    error: null
  };

  componentDidMount() {
    // Check if user is already authenticated
    const storedUser = localStorage.getItem("user");

    if (storedUser) {
      this.setState({
        isAuthenticated: true,
        user: JSON.parse(storedUser)
      });
    }
  }

  login = async (credentials) => {
    // Perform authentication logic (e.g., call an API endpoint)
    try {
      const response = await axios.post("/api/login", credentials);

      // Store user data locally
      localStorage.setItem("user", JSON.stringify(response.data));

      // Update state
      this.setState({
        isAuthenticated: true,
        user: response.data,
        error: null
      });
    } catch (error) {
      this.setState({
        isAuthenticated: false,
        user: null,
        error: "Invalid credentials. Please try again."
      });
    }
  };

  logout = () => {
    // Clear user data from local storage
    localStorage.removeItem("user");

    // Update state
    this.setState({
      isAuthenticated: false,
      user: null,
      error: null
    });
  };

  render() {
    const { isAuthenticated, user, error } = this.state;

    return (
      
        {this.props.children}
      
    );
  }
}
            
        

In this code snippet, we define the AuthContext and AuthProvider components. The AuthProvider component holds the state related to authentication and provides the login and logout methods to update the state.

Step 2: Create Login Component

Next, create a Login component where users can enter their credentials and authenticate themselves. Here's an example implementation:

            
import React, { useContext, useState } from "react";
import { AuthContext } from "./context";

function Login() {
  const { login, error } = useContext(AuthContext);
  const [credentials, setCredentials] = useState({
    email: "",
    password: ""
  });

  const handleChange = (e) => {
    setCredentials({
      ...credentials,
      [e.target.name]: e.target.value
    });
  };

  const handleSubmit = (e) => {
    e.preventDefault();

    login(credentials);
  };

  return (
    
{error &&

{error}

}
); } export default Login;

In this code snippet, we use the useContext hook to access the login function from the AuthContext. The login function is called when the form is submitted, and it takes care of authenticating the user.

Step 3: Create Protected Route

Create a protected route component that restricts access to authenticated users. You can define this component as follows:

            
import React, { useContext } from "react";
import { Route, Redirect } from "react-router-dom";
import { AuthContext } from "./context";

function ProtectedRoute({ component: Component, ...rest }) {
  const { isAuthenticated } = useContext(AuthContext);

  return (
    
        isAuthenticated ?  : 
      }
    />
  );
}

export default ProtectedRoute;
            
        

In this code snippet, we use the useContext hook to access the isAuthenticated state from the AuthContext. If the user is authenticated, the component specified in the component prop is rendered. Otherwise, the user is redirected to the login page.

Step 4: Set Up Routes

Finally, set up your routes in the main component of your application, making use of the ProtectedRoute component to restrict access to certain pages. Here's an example:

            
import React from "react";
import { BrowserRouter as Router, Switch } from "react-router-dom";
import { AuthProvider } from "./context";
import ProtectedRoute from "./ProtectedRoute";
import Dashboard from "./Dashboard";
import Profile from "./Profile";
import Login from "./Login";

function App() {
  return (
    
      
        
          
          
          
        
      
    
  );
}

export default App;
            
        

In this code snippet, we use the ProtectedRoute component to protect the /dashboard and /profile routes. Only authenticated users can view these pages, and if a user is not authenticated, they are redirected to the login page.

Conclusion

By leveraging the capabilities of react-router-dom and Context API, you can easily create protected routes in your React application. This ensures better security and authorization, allowing only authenticated users to access certain pages or components.