Mastering User Authentication with React Router v6

Setting Up React Router v6

To get started, create a new React project and install React Router v6 using npm or yarn. Then, edit the src/main.js file to import BrowserRouter from react-router-dom and wrap the <App /> component with <BrowserRouter />.

import { BrowserRouter } from 'eact-router-dom';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>
);

Basic Routing with React Router v6

React Router v6 provides two primary components for routing: <Routes /> and <Route />. The <Routes /> component is an alternative to the <Switch /> component from React Router v5, while the <Route /> component provides the mapping between paths on the app and different React components.

import { Routes, Route } from 'eact-router-dom';
import HomePage from './pages/HomePage';
import LoginPage from './pages/LoginPage';

function App() {
  return (
    <Routes>
      <Route path="/" element=<HomePage /> />
      <Route path="/login" element=<LoginPage /> />
    </Routes>
  );
}

Creating Protected Routes

Protected routes are essential for restricting access to certain pages or resources to authenticated users only. To implement protected routes, create a custom useAuth Hook to manage the authenticated user’s state using React’s Context API and useContext Hook.

import { createContext, useContext, useState } from 'eact';

const AuthContext = createContext();

export function useAuth() {
  const context = useContext(AuthContext);
  if (!context) {
    throw new Error('useAuth must be used within an AuthProvider');
  }
  return context;
}

export function AuthProvider({ children }) {
  const [user, setUser] = useState(null);

  const login = (userData) => {
    setUser(userData);
  };

  const logout = () => {
    setUser(null);
  };

  return (
    <AuthContext.Provider value={{ user, login, logout }}>
      {children}
    </AuthContext.Provider>
  );
}

Implementing Two-Factor Authentication

Two-factor authentication adds an extra layer of security by requiring users to provide two distinct forms of identification before accessing sensitive features. To implement two-factor authentication, modify the existing authentication setup to include 2FA.

import { useAuth } from './useAuth';

function LoginPage() {
  const { login } = useAuth();
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  const [twoFactorCode, setTwoFactorCode] = useState('');

  const handleSubmit = async (event) => {
    event.preventDefault();
    try {
      await login(username, password, twoFactorCode);
    } catch (error) {
      console.error(error);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>
        Username:
        <input type="text" value={username} onChange={(e) => setUsername(e.target.value)} />
      </label>
      <br />
      <label>
        Password:
        <input type="password" value={password} onChange={(e) => setPassword(e.target.value)} />
      </label>
      <br />
      <label>
        2FA Code:
        <input type="text" value={twoFactorCode} onChange={(e) => setTwoFactorCode(e.target.value)} />
      </label>
      <br />
      <button type="submit">Login</button>
    </form>
  );
}

Using Nested Routes and <Outlet />

Nested routes allow us to have a route that contains other child routes. The <Outlet /> component enables nested UI elements to be visible when child routes are rendered.

import { Routes, Route, Outlet } from 'eact-router-dom';
import HomePage from './pages/HomePage';
import LoginPage from './pages/LoginPage';
import ProfilePage from './pages/ProfilePage';

function App() {
  return (
    <Routes>
      <Route path="/" element=<HomePage /> />
      <Route path="/login" element=<LoginPage /> />
      <Route path="/profile" element=<>
        <Outlet />
        <Route index element=<ProfilePage /> />
      </Route>
    </Routes>
  );
}

function ProfilePage() {
  return (
    <div>
      <h1>Profile Page</h1>
      <p>This is the profile page.</p>
    </div>
  );
}

Leave a Reply