4 min read
React Router & API Integration
Mind Map Summary
- Client-Side Routing (React Router)
- What: Enables building Single-Page Applications (SPAs) where navigation doesn’t require a full page refresh.
- Key Components:
<BrowserRouter>: The routing context provider.<Routes>: Container for matching routes.<Route>: Defines path-to-component mapping.<Link>: Safe navigation component (replaces<a>).
- Hooks:
useNavigate(): Programmatic navigation.useParams(): Access dynamic URL parameters.
- API Integration
- The Pattern:
- Trigger:
useEffectstarts the scan on mount or parameter change. - States:
data(results),loading(boolean), anderror(failure details). - Mechanism: Browser
fetchoraxios.
- Trigger:
- The Pattern:
Core Concepts
1. React Router
In a traditional website, clicking a link causes a full page reload. In an SPA, React Router intercepts navigation events and swaps components locally. This results in a faster, more app-like experience.
<BrowserRouter>: Place this at the root of your application.<Routes>and<Route>: This is your site’s manifest. The first matching path wins.<Link>: Use this instead of<a>to prevent the browser from reloading the entire HTML document.
2. API Data Fetching Lifecycle
Fetching data is an asynchronous “side effect.” You must manage its state to ensure a good user experience:
- Mounting: Component shows a loading indicator (e.g., a spinner).
- Request:
useEffectcalls the API. - Success: API returns 2xx. Update
dataand setloadingtofalse. - Error: API returns 4xx/5xx or network fails. Update
errorand setloadingtofalse.
Practice Exercise
Create a multi-page app with React Router where one page dynamically fetches GitHub profile data based on a URL parameter.
Answer
1. The Main Router (App.jsx)
import React from "react";
import { Routes, Route, Link } from "react-router-dom";
import UserProfile from "./UserProfile";
export default function App() {
return (
<div className="container">
<nav>
<Link to="/">Home</Link> | <Link to="/user/facebook">FB Example</Link>
</nav>
<hr />
<Routes>
<Route path="/" element={<h2>Home Page</h2>} />
<Route path="/user/:username" element={<UserProfile />} />
</Routes>
</div>
);
}
2. The Data Fetching Component (UserProfile.jsx)
import React, { useState, useEffect } from "react";
import { useParams } from "react-router-dom";
export default function UserProfile() {
const { username } = useParams();
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
setLoading(true);
setError(null);
fetch(`https://api.github.com/users/${username}`)
.then((res) => {
if (!res.ok) throw new Error("User not found");
return res.json();
})
.then((data) => {
setUser(data);
setLoading(false);
})
.catch((err) => {
setError(err.message);
setLoading(false);
});
}, [username]); // Re-run whenever the URL param changes
if (loading) return <div className="spinner">Loading profile...</div>;
if (error) return <div className="alert">Error: {error}</div>;
return (
<article className="profile">
<h2>{user.name}</h2>
<img src={user.avatar_url} alt={user.login} width="120" />
<p>{user.bio}</p>
</article>
);
}
Why This Architecture Works
- Declarative Navigation: You define “what” should show for a URL, not “how” to manipulate the DOM.
- Responsiveness: The
loadingstate prevents a “broken” look while waiting for slow networks. - Resilience: The
errorstate handles edge cases like invalid usernames gracefully. - Referential Integrity: Using
[username]in theuseEffectdependency array ensures the component updates correctly even if the user navigates between different profile pages.