How do you implement routing in React applications? Compare different routing solutions.

3 minintermediatereactroutingapplicationssolutions

Quick Answer

Routing in React applications is typically handled by client-side routing libraries since React is a single-page application framework.

Detailed Answer

How do you implement routing in React applications? Compare different routing solutions.

Answer:

Routing in React applications is typically handled by client-side routing libraries since React is a single-page application framework.

React Router (Most Popular):

import { BrowserRouter, Routes, Route, Link, useParams, useNavigate } from 'react-router-dom';

// Basic routing setup
function App() {
  return (
    <BrowserRouter>
      <nav>
        <Link to="/">Home</Link>
        <Link to="/about">About</Link>
        <Link to="/users">Users</Link>
      </nav>
      
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="/users" element={<Users />} />
        <Route path="/users/:id" element={<UserDetail />} />
        <Route path="*" element={<NotFound />} />
      </Routes>
    </BrowserRouter>
  );
}

// Using route parameters
function UserDetail() {
  const { id } = useParams<{ id: string }>();
  const navigate = useNavigate();
  
  return (
    <div>
      <h2>User {id}</h2>
      <button onClick={() => navigate('/users')}>
        Back to Users
      </button>
    </div>
  );
}

// Protected routes
function ProtectedRoute({ children }: { children: React.ReactNode }) {
  const { user } = useAuth();
  
  if (!user) {
    return <Navigate to="/login" replace />;
  }
  
  return <>{children}</>;
}

// Usage
<Route 
  path="/dashboard" 
  element={
    <ProtectedRoute>
      <Dashboard />
    </ProtectedRoute>
  } 
/>

Nested Routes:

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Layout />}>
          <Route index element={<Home />} />
          <Route path="products" element={<Products />}>
            <Route index element={<ProductList />} />
            <Route path=":id" element={<ProductDetail />} />
            <Route path="new" element={<NewProduct />} />
          </Route>
          <Route path="about" element={<About />} />
        </Route>
      </Routes>
    </BrowserRouter>
  );
}

function Layout() {
  return (
    <div>
      <Header />
      <main>
        <Outlet /> {/* Renders child routes */}
      </main>
      <Footer />
    </div>
  );
}

Route Guards and Authentication:

// Custom hook for authentication
function useAuth() {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);
  
  useEffect(() => {
    checkAuth().then(user => {
      setUser(user);
      setLoading(false);
    });
  }, []);
  
  return { user, loading };
}

// Protected route component
function ProtectedRoute({ children, requiredRole }: { 
  children: React.ReactNode; 
  requiredRole?: string;
}) {
  const { user, loading } = useAuth();
  const location = useLocation();
  
  if (loading) {
    return <div>Loading...</div>;
  }
  
  if (!user) {
    return <Navigate to="/login" state={{ from: location }} replace />;
  }
  
  if (requiredRole && user.role !== requiredRole) {
    return <Navigate to="/unauthorized" replace />;
  }
  
  return <>{children}</>;
}

// Usage
<Route 
  path="/admin" 
  element={
    <ProtectedRoute requiredRole="admin">
      <AdminPanel />
    </ProtectedRoute>
  } 
/>

Alternative Routing Solutions:

1. Next.js Router (File-based routing):

// pages/index.tsx
import { useRouter } from 'next/router';

export default function Home() {
  const router = useRouter();
  
  const handleNavigate = () => {
    router.push('/about');
  };
  
  return (
    <div>
      <h1>Home Page</h1>
      <button onClick={handleNavigate}>Go to About</button>
    </div>
  );
}

// pages/users/[id].tsx - Dynamic route
export default function UserDetail() {
  const router = useRouter();
  const { id } = router.query;
  
  return <div>User ID: {id}</div>;
}

2. Wouter (Lightweight alternative):

import { Router, Route, Link, useLocation } from 'wouter';

function App() {
  return (
    <Router>
      <nav>
        <Link href="/">Home</Link>
        <Link href="/about">About</Link>
      </nav>
      
      <Route path="/" component={Home} />
      <Route path="/about" component={About} />
      <Route path="/users/:id" component={UserDetail} />
    </Router>
  );
}

3. Reach Router (Deprecated, but concepts still relevant):

// Focus management and accessibility features
import { Router, Link, navigate } from '@reach/router';

function App() {
  return (
    <Router>
      <Home path="/" />
      <About path="/about" />
      <Users path="/users" />
      <UserDetail path="/users/:id" />
    </Router>
  );
}

Routing Best Practices:

  1. Use BrowserRouter for production - Provides clean URLs
  2. Implement route guards - Protect sensitive routes
  3. Handle loading states - Show loading indicators during navigation
  4. Use lazy loading - Code split routes for better performance
  5. Handle 404s - Provide fallback routes
  6. Consider SEO - Use proper meta tags and structured data
// Lazy loading routes
const Home = lazy(() => import('./pages/Home'));
const About = lazy(() => import('./pages/About'));

function App() {
  return (
    <BrowserRouter>
      <Suspense fallback={<div>Loading...</div>}>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/about" element={<About />} />
        </Routes>
      </Suspense>
    </BrowserRouter>
  );
}