Question presented to candidate: "Build the like button you see under a social media post. Clicking it should feel instant, even though the like is saved on a server that takes a moment and sometimes fails. If the save fails, put things back the way they were and tell the user. You can fake the server."
Requirements:
- A Like button and a count ("41 likes"); clicking toggles liked or unliked and moves the count by one.
- Optimistic update: the button and count change immediately, before the server answers.
- A simulated API (a Promise that resolves or rejects after about 600 ms); a switch to force failures.
- On failure, roll back to the exact previous state and show a message.
- Ignore clicks while a save is in flight (or explain the alternative you choose).
- Accessible toggle semantics and a small "pop" animation that respects reduced motion.
What a strong answer should cover:
- Why optimistic UI: perceived speed, and the price you pay (handling failure).
- A snapshot of the previous state taken before the update, restored in
catch. - A guard for concurrent requests (a ref or plain variable, not state) and the trade-off versus "last click wins".
aria-pressedfor a toggle button with a stable label, and a status live region for "Saving…" and errors.- Injecting the save function as a prop so the button is testable and reusable.
Clarifying questions expected:
- "Can the user click again while a request is in flight? Should the last click win?"
- "Does the server return the authoritative count I should reconcile with?"
- "Should a failure retry automatically, or just inform the user?"
Code / implementation expected: Yes. A working component plus a fake API function, roughly 60-90 lines.