Module 3: Routing & API

React Router DOM and Fetching Data.

1. Core Concepts

React Router: React is a "Single Page App" (SPA). We don't reload the browser to change pages; we just swap components.

Fetching Data: Usually done in useEffect. You must handle 3 states: Loading (spinner), Error (message), and Data (content).

1.1 Deep Dive: Client-Side Routing vs. Server-Side Routing

Traditional websites request a new HTML file for every page load. React SPAs (Single Page Applications) load one HTML file once. When you click a link, JavaScript intercepts the click, changes the URL in the address bar (using the History API), and swaps the components on the screen. This is instant but requires careful management of browser history and scroll position.

1.2 Industry Standard: The Service Layer

Senior developers never call fetch directly inside a component. They create a "Service Layer" or "API Client". This makes code reusable and testable.

// api/userApi.ts
export const getUser = async (id: string) => {
  const response = await fetch(`/api/users/${id}`);
  if (!response.ok) throw new Error('Failed to fetch');
  return response.json();
};

// Component
// import { getUser } from '../api/userApi';
// ... inside useEffect ...
getUser(id).then(setData).catch(setError);
📚 Deep Dive (Documentation)

2. The Setup Challenge

Task: Install Router

Install react-router-dom.

Refactor your App.tsx to use BrowserRouter, Routes, and Route.

Create two pages: Home and Users.

REQ-004 To Do

Build "User Directory" with Dynamic Routing

User Story

As an admin, I need to browse a list of users and click on any user to view their full profile details.

Acceptance Criteria
  • Users Page (/users):
    • Fetch users from https://jsonplaceholder.typicode.com/users.
    • Show a "Loading..." spinner while fetching.
    • Display a list of users (Name, Email).
    • Link each name to /users/:id.
  • User Detail Page (/users/:id):
    • Use useParams to extract the ID.
    • Fetch details for that specific user.
    • Display full address and company info.
    • Add a "Back to List" button.
Senior Bonus
  • Error Handling: If the API fails (simulate by blocking network), show a friendly "Something went wrong" UI, not a blank screen.
  • 404 Handling: If the user ID doesn't exist (e.g., ID 999), show a "User Not Found" message.
  • Service Layer: Extract all fetch calls into a separate api.ts file.

3. The Bug Hunt

🐛 Scenario: The Race Condition

The Setup:

You click "User 1", then quickly click "User 2". The network is slow. "User 2" data arrives first, then "User 1" data arrives later and overwrites the screen.

The Bug: You are on the URL for User 2, but seeing data for User 1.

The Task:

  1. Reproduce this by adding a random delay to your fetch.
  2. Fix it using a boolean flag ignore in the useEffect cleanup function.
useEffect(() => {
  let ignore = false;
  fetchUser(id).then(data => {
    if (!ignore) setUser(data);
  });
  return () => { ignore = true; };
}, [id]);