Lesson 8 Lab — A Category Detail View¶
Build a read-only Category detail page reached by id (/categories/detail/:id),
following the Order Detail pattern from the guide — useParams to read the id,
fetch the one record, render it as a definition list. Category is a simple entity,
so this is the detail pattern at its smallest. Refer back to the guide for useParams,
the undefined-initialized state guard, and the <dl> layout.
Prerequisite: your API is running on the HTTP profile (
http, nothttps) with Categories seed data loaded.Note: you already started the Categories module in Lesson 7 (the
ICategoryinterface + alist()for the Menu Item form's dropdown). Here you add afindand a detail view — extra practice for the detail/params pattern. The finished reference app has no Category detail page, so reach it by typing the URL; the Categories list and form come in the Lesson 9–10 labs.
The Category record¶
id, name, sortOrder. (That's the whole entity — no FK, no nested collections.)
Steps¶
Same arc as the guide, on the simplest entity: find → fetch by :id → definition list.
- Add
find(id)(GET/api/categories/{id}) to theCategoryAPIyou started in Lesson 7 (it already hasICategoryandlist). You adddelete/post/putin the Lesson 9–10 labs. - Build
CategoryDetailPage: read:idwithuseParams,Number(id)it, and fetch intouseState<ICategory | undefined>(undefined)in auseEffect. - Guard the render with
{category && …}; show a{loading && <p>Loading…</p>}while fetching. - Render a heading row ("Category") and a
<dl>(inside ad-flex flex-wrap gap-4row) showing Name and Sort Order as<dt>/<dd>pairs. - Add the
categories/detail/:idroute underLayout. (An Edit pencilLinkto/categories/edit/:idin the heading will 404 until the Lesson 10 lab builds the form — add it now or later.) ✅ Checkpoint: type/categories/detail/5in the address bar → the detail renders; change the id → a different category loads. (There's no list or card to click from yet — the Lesson 9 lab builds the Category card, where you can add a View item that links here.)
Verify in the browser¶
Browser checks are covered in the guide — section 5. With your API running and
npm run dev up:
- Type
/categories/detail/5in the address bar → the page shows that category's Name and Sort Order. - Change the id in the URL and reload — a different category loads (that's
useParamsplus the keyed fetch). - If you added the Edit link, clicking it 404s for now — the category edit form is the Lesson 10 lab.
- Console clean; Network shows
GET /api/categories/{id}.
Same useParams + detail pattern on the simplest entity — the mechanics you'll reuse
on PRS's Request Detail (which adds workflow buttons and a child table in the next
lessons).
Stretch challenges¶
Optional — for when you finish early. Not needed for the capstone. [Reinforce] builds on what you just did; [Reach] goes past the guide and needs some research.
- Menu items in this category — [Reinforce] — below the summary, fetch
/api/menuitems, filter to those whosecategoryIdmatches, and list their names. Practice combining a route param with a second fetch and a.filter(). - Not-found handling — [Reinforce] — if the fetch returns nothing (bad id), render a
"Category not found" message instead of a blank summary, using a ternary on the
categorystate. - Back button — [Reinforce] — add a "Back to Categories" button that calls
navigate("/categories")viauseNavigate, reinforcing code-driven navigation. - Read the raw param — [Reach] —
console.log(useParams())and confirm the id is a string, then trace where you convert it withNumber(...). Read why params are strings. Reference: useParams (react-router v6).
Finished these and want more? See stretch-react-challenges.md for bigger challenges that span the whole React pass.