3. Data Fetching & Routing
Goal for this page: replace hardcoded data with a real dummy-API call, split the app into
multiple pages, and make search shareable through the URL. You'll also create your first
dataSource/ layer — the same idea AquaGen uses.
Step 3.1 — Fetch data through a dataSource file
What & why: Apps get their data from HTTP APIs. Rather than scattering axios calls across
components, put them in one place per data source — a dataSource/ file. Your components
call a function like getItems() and don't care how the data arrives. This is exactly how
AquaGen organizes API calls (libs/<feature>/src/dataSource/).
Learn:
- Axios — intro (the HTTP client our production app uses)
- MDN: Using the Fetch API (the built-in alternative)
- React: Fetching data in an Effect (and its caveats)
Your task: Install axios. Create src/dataSource/items.js exporting a getItems()
function that fetches the list from your chosen dummy API. In your list component, call it on
mount (with useEffect) and render a Card per item. Handle all three states — show
"Loading…" while the request is in flight and an error message if it fails. Throttle your
network in DevTools to confirm the loading state actually appears.
Step 3.2 — Add routing with React Router
What & why: Multi-page apps need a router to map URLs to components without full page reloads. AquaGen uses React Router 7, so use v7 here too.
Learn:
- React Router — Installation & your first router
- React Router — Routing & nested routes
- React Router — Navigating with
Link
Your task: Set up the router with two routes: a list page (/) and a detail page
(/items/:id). Make each Card a Link to its detail route.
Step 3.3 — Read route params with useParams
What & why: The detail page needs to know which item to show. Dynamic segments like :id
are read with the useParams hook, then used to fetch that one item — through your dataSource
layer again.
Learn:
Your task: Add a getItem(id) function to dataSource/items.js. On the detail page, read
the :id with useParams, call getItem(id), and display the item's full details. Handle
loading/error here too.
Step 3.4 — Search & filter via query params
What & why: Filters, search terms, and pagination belong in the URL (?q=…&page=2) so a
view is bookmarkable and shareable. useSearchParams reads and writes them.
Learn:
Your task: Move your search box so the typed term lives in the URL as ?q=…. Reload the page
and confirm the search term (and results) persist from the URL. Bonus: add a ?page= param and
wire it to your dummy API's pagination.
Your app now loads real data through a dataSource layer, has multiple routed pages, and
its search state lives in the URL. Next, share state across the whole app and start reusing your
logic.
Next: → Context & custom hooks