FrontendPro

120Build a fault-tolerant React checkout flow with idempotent submission, recovery, and persistent state

hardAbout 75 minutesCodingreactpaymentsidempotencyresilience

Problem

Checkout is where bugs cost real money: a double click charges twice, a network drop loses the order, a refresh loses the form. Build <Checkout cart={items} api={api} storage={storage} createKey={() => crypto.randomUUID()} />.

  • api.placeOrder({ idempotencyKey, items, address }) resolves with { orderId }. It rejects with a TypeError on network failure, or with an error that has a status (for example 402 when the payment is declined).
  • api.getOrderStatus(idempotencyKey) resolves with { status: "confirmed", orderId } or { status: "not_found" }.
  • storage has getItem, setItem and removeItem (like localStorage).

Requirements

  • Inputs aria-label="Name" and aria-label="Address"; the draft { name, address } is saved to storage under "checkout:draft" on every change and restored on mount.
  • Place order submits once: the button is disabled while submitting, and a double click never sends two requests.
  • Each order attempt has an idempotency key. Save { key, items, address } under "checkout:pending" before calling the API.
  • On a network error, show Retry, which resends with the same key (so the server can recognise a duplicate).
  • On a 4xx error, show the error in role="alert", discard the pending attempt, and use a new key for the next attempt.
  • On success, show Order {orderId} confirmed, and remove both storage entries.
  • Recovery: if "checkout:pending" exists on mount (the tab crashed or was closed mid-request), do not submit again. Show "Checking your previous order…", call getOrderStatus(key): confirmed → show the confirmation and clean up; not found → show Retry with the same key.

Try it yourself

Write your solution, run it, then submit to check it against the tests.

App.jsxReact + DOM

Step-by-step

Write the pending attempt (key, items, address) to storage before sending the request. If the tab dies after the server charged the card but before the response arrives, the next visit knows an attempt is outstanding and asks the server instead of charging again.

Unlock the full solution

What's inside

  • Step-by-step
  • Approach
  • Solution
  • Complexity
  • Edge cases
  • Follow-up questions
  • Tests

Includes 2 code listings, 5 edge cases, 4 follow-up questions.

One-time payment by UPI, card or net banking. Launch price.

All 150 answersOne payment, yours forever