A page for each product doesn't need eight routes. A route's path can have a URL parameter, a part that starts with a colon: /products/:id matches /products/1, /products/3 and every other id. The given src/App.jsx already has this route, and each product card now has a Details link that points to it.
Inside the page, useParams() returns the parameters as an object of strings, one key per :name. For an orders page on the route /orders/:orderId, at the address /orders/12:
const { orderId } = useParams(); // "12"
The page uses the id to load its data in an effect, and lists id in the effect's dependencies. When the visitor goes from one product to the next, React Router keeps the same page and only gives it a new id. With [id], the effect runs again and loads the new product. Opening an address like /products/3 directly works the same way.
The check clicks Details on the Lamp, then Next product, then Back, then opens /products/3. Your page must give:
> click "Details" in "Lamp" (address: /products/3) request: GET /api/products/3 -> 200 screen: heading 2: Lamp, text: $29, text: 1 in stock > click "Next product" (address: /products/4) request: GET /api/products/4 -> 200 screen: heading 2: Pen, text: $2, text: 120 in stock > press the browser's Back button (address: /products/3) request: GET /api/products/3 -> 200 screen: heading 2: Lamp … > open /products/3 request: GET /api/products/3 -> 200 screen: heading 2: Lamp …
Your task: in src/ProductPage.jsx, take id out of useParams(). Then, in an effect with [id] as its dependencies, load the product with getProduct(id) and give it to setProduct. The loading text and the product's section are already written.
Assignment
Follow the Coding Tutorial to make the product page read its id from the address and load that product.
Hint
An effect's function can't be async itself: write an async function inside the effect, then call it. Without setProduct, the page stays on Loading the product… even after the API answers.
Free plan: 30 tutor messages. PRO is unlimited.
