The third slice of the wishlist is the page's data, in client/src/useWishlist.js. A hook keeps the ids of the visitor's saved products and gives the page two functions: has(id), for the button's pressed state, and toggle(id), for its click. The product page that uses them is given.
The hook loads the ids with GET /api/wishlist when a visitor is logged in, and clears them for a guest. Its effect depends on [user], so it runs again after a login or a logout.
toggle makes an optimistic update: it changes the screen first, then sends PUT or DELETE, and puts the old state back if the server refuses. A like button could work the same way:
async function like() {
setLiked(true);
try {
await api("/api/posts/3/like", { method: "PUT" });
} catch (err) {
setLiked(false);
}
}
The check opens the Teapot's page, logs in as Ana, saves the Teapot, reloads, then makes the API refuse the DELETE. The end of what it prints:
> click "Save for later"
request: PUT /api/wishlist/6 ...
screen while waiting:
button: Save for later (pressed)
answer: PUT /api/wishlist/6 -> 204
> reload the page
request: GET /api/wishlist -> 200
button: Save for later (pressed)
> the API will answer DELETE /api/wishlist/6 with 500
> click "Save for later"
request: DELETE /api/wishlist/6 ...
screen while waiting:
button: Save for later
answer: DELETE /api/wishlist/6 -> 500
screen:
button: Save for later (pressed)
Your task: fill in useWishlist: the ids state, the effect that loads them, has, and toggle's quick change, request and undo.
Assignment
Follow the Coding Tutorial to write the wishlist hook in client/src/useWishlist.js, one line at a time.
Hint
In the catch, ids still holds the list from before the click, so setIds(ids) puts the screen back as it was.
Free plan: 30 tutor messages. PRO is unlimited.
