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.
BrowserRouter: The manager. Wraps the app.Routes/Route: The map. "If URL is /about, show AboutComponent".Link: The anchor tag replacement. Prevents full page reload.
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.
Build "User Directory" with Dynamic Routing
As an admin, I need to browse a list of users and click on any user to view their full profile details.
- 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.
- Fetch users from
- User Detail Page (
/users/:id):- Use
useParamsto extract the ID. - Fetch details for that specific user.
- Display full address and company info.
- Add a "Back to List" button.
- Use
- 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.tsfile.
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:
- Reproduce this by adding a random delay to your fetch.
- Fix it using a boolean flag
ignorein theuseEffectcleanup function.
useEffect(() => {
let ignore = false;
fetchUser(id).then(data => {
if (!ignore) setUser(data);
});
return () => { ignore = true; };
}, [id]);