# claude session d02659b5-ec03-4d34-b363-1f0767df0d19 ## 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 ; 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 ;\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 \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" } ```