The cart lives on the server now, but many parts of the page need it: the header's Cart (2) link, the products page's "Add to cart" buttons, the cart page. Instead of each fetching its own copy, one provider keeps the cart in state and shares it through a React context. Any component reads it with useCart(); the given main.jsx already wraps the app in <CartProvider>.
The provider loads GET /api/cart in an effect. A reload clears every state, and the page only knows who is logged in once GET /api/me answers, so the effect depends on [user] and returns at once while there is no user. The given AuthContext.jsx loads the user with the same pattern, an async function inside the effect:
useEffect(() => {
async function loadUser() {
try {
const data = await api("/api/me");
setUser(data);
} catch (err) {
setUser(null);
} finally {
setLoading(false);
}
}
loadUser();
}, []);
To add a product, add(productId) posts {product_id, quantity: 1} and puts the answer in state as it is. The server's answer is the whole new cart, so the page never adds lines or totals itself.
The check logs in as Ana, adds the Mug and the Teapot, opens the cart, then reloads it:
log in → POST /api/login 200, GET /api/cart 200, GET /api/products 200
Add to cart, Mug → POST /api/cart {"product_id": 1, "quantity": 1} → 200 link: Cart (1)
Add to cart, Teapot → POST /api/cart {"product_id": 6, "quantity": 1} → 200 link: Cart (2)
open /cart → Mug × 1 $12, Teapot × 1 $22, Total: $34, link: Cart (2)
reload the page → Cart (0) while GET /api/me waits, then GET /api/cart 200 and Cart (2)
Your task: in client/src/CartContext.jsx, take user from useAuth(), load the cart in a useEffect with [user] (returning at once when there is no user), and fill in add: post to /api/cart and give the answer to setCart.
Assignment
Follow the Coding Tutorial to make the cart provider load the user's cart from the server and keep it up to date when a product is added.
Hintapi(path, { method: "POST", body: … }) sends the request and gives back the JSON answer. An effect's function can't be async itself, so write an async function inside it and call it.
Free plan: 30 tutor messages. PRO is unlimited.
