web-app/users/leo@acme.dev/sessions/d02659b5-ec03-4d34-b363-1f0767df0d19/commits/dc7bd6474afa/conversation.md
78 lines · 2.5 KBRaw
Conversation behind dc7bd6474afa: Disable checkout button while the order is pending
User
On slow 3G the checkout button flickers and some people manage to place the order twice. Fix it.
Tool call: Read
{
"file_path": "/home/dev/code/web-app/src/components/CheckoutButton.tsx"
}
Tool result
1 export function CheckoutButton({ cart }: { cart: Cart }) {
2 const [loading, setLoading] = useState(false);
3
4 async function submit() {
5 setLoading(true);
6 await placeOrder(cart);
7 setLoading(false);
8 }
9
10 return <button onClick={submit}>{loading ? <Spinner /> : "Place order"}</button>;
11 }
Assistant (thinking)
The button is never disabled, so a second tap during the request fires submit again. The flicker is the label swapping to a spinner, which changes the button width. Disable while pending, guard with a ref (state updates are async, two fast taps both see loading=false), and keep the width fixed.
Tool call: Edit
{
"file_path": "/home/dev/code/web-app/src/components/CheckoutButton.tsx",
"old_string": " const [loading, setLoading] = useState(false);\n\n async function submit() {\n setLoading(true);\n await placeOrder(cart);\n setLoading(false);\n }\n\n return <button onClick={submit}>{loading ? <Spinner /> : \"Place order\"}</button>;\n",
"new_string": " const [loading, setLoading] = useState(false);\n const inFlight = useRef(false); // two quick taps both see loading=false\n\n async function submit() {\n if (inFlight.current) return;\n inFlight.current = true;\n setLoading(true);\n try {\n await placeOrder(cart);\n } finally {\n inFlight.current = false;\n setLoading(false);\n }\n }\n\n return (\n <button onClick={submit} disabled={loading} aria-busy={loading} style={{ minWidth: 140 }}>\n {loading ? <Spinner /> : \"Place order\"}\n </button>\n );\n"
}
Tool result
The file src/components/CheckoutButton.tsx has been updated.
Tool call: Bash
{
"command": "npx tsc --noEmit",
"description": "Type check"
}
Tool result
Assistant
The button is disabled while the order is pending, a ref blocks a second tap that lands before the re-render, and a fixed min-width stops the flicker when the label swaps to the spinner.
Tool call: Bash
{
"command": "git commit -am \"Disable checkout button while the order is pending\"",
"description": "Commit"
}