mirror of
https://github.com/stack-auth/stack.git
synced 2026-07-20 21:29:36 +08:00
Fix item quantity dialog balance preview flicker on submit (#1774)
## Problem On a customer's payments view, submitting a manual item quantity change makes the "New balance: X → Y" preview in the dialog briefly flip to the post-change values (e.g. `0 → 10` flashes to `10 → 20`) right before the dialog closes. ## Root cause The preview was computed from the live `currentQuantity` prop, which comes from `useItem()` in the parent row. The SDK's `createItemQuantityChange` awaits its item cache refresh before resolving, so the prop updates to the new quantity while the dialog is still open (and stays visible through the close animation), recomputing the preview with stale input text. ## Fix Snapshot the quantity when the dialog opens (in the existing reset-on-open effect) and compute the preview from the snapshot instead of the live prop. The preview now consistently shows the balance as of when the dialog was opened. ## Before vs after Recorded against built servers (before = `dev`, after = this branch). The transactions refetch is artificially delayed by 5s in both recordings to stretch the flicker window to a visible length — on production latency it's a split-second flash. https://github.com/user-attachments/assets/c005ef3b-45cb-4b75-bd71-5f723eae0c50 ## Tradeoffs If the quantity changes externally while the dialog is open, the preview shows the value from open time. The mutation is a delta, so correctness of the applied change is unaffected. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Stabilized the quantity change preview while the dialog is open. * The “New balance” display now consistently shows the quantity at opening and the calculated updated quantity, even if underlying values change during submission. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
parent
4b371e5c36
commit
33a7ef5485
@ -44,6 +44,10 @@ export function ItemQuantityChangeDialog(props: Props) {
|
||||
const [description, setDescription] = useState("");
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
// Snapshot the quantity at dialog open: the live prop updates mid-submit
|
||||
// (the SDK refreshes the item cache before resolving), which would flip the
|
||||
// "X → Y" preview to the post-change values right before the dialog closes.
|
||||
const [quantityAtOpen, setQuantityAtOpen] = useState(props.currentQuantity);
|
||||
|
||||
// Reset the form whenever the dialog is (re)opened so stale input doesn't
|
||||
// leak across invocations.
|
||||
@ -52,11 +56,13 @@ export function ItemQuantityChangeDialog(props: Props) {
|
||||
setQuantityText("");
|
||||
setDescription("");
|
||||
setError(null);
|
||||
setQuantityAtOpen(props.currentQuantity);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps -- snapshot only on open
|
||||
}, [props.open]);
|
||||
|
||||
const parsedQuantity = parseQuantityChange(quantityText);
|
||||
const newQuantity = parsedQuantity == null ? null : props.currentQuantity + parsedQuantity;
|
||||
const newQuantity = parsedQuantity == null ? null : quantityAtOpen + parsedQuantity;
|
||||
|
||||
const submit = async () => {
|
||||
if (parsedQuantity == null) {
|
||||
@ -143,7 +149,7 @@ export function ItemQuantityChangeDialog(props: Props) {
|
||||
<Typography type="label" className="text-muted-foreground text-xs">
|
||||
{newQuantity == null
|
||||
? "Positive values add to the balance, negative values subtract."
|
||||
: `New balance: ${props.currentQuantity} → ${newQuantity}`}
|
||||
: `New balance: ${quantityAtOpen} → ${newQuantity}`}
|
||||
</Typography>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user