When a customer changes their shipping state from CA to NY in the checkout form and the displayed shipping cost stays frozen at the California rate, they proceed to payment believing one price and are charged another — a CWE-682 calculation error surfaced at the worst possible moment. ISO 25010:2011 functional correctness and user-experience taxons both apply: the checkout summary is a live contract between the store and the customer. Stale rates cause payment disputes and undermine trust in the exact moment checkout confidence is most fragile. Address-change handlers that call no recalculation function are dead code with real financial consequences.
High because stale shipping costs displayed at the payment step produce direct financial discrepancies that lead to customer disputes and erode checkout conversion.
Wire onChange handlers on state, zip, and country fields in components/ShippingAddressForm.tsx to invoke a shipping recalculation and update the summary without a reload:
// components/ShippingAddressForm.tsx
export function ShippingAddressForm({ onAddressChange }) {
const [address, setAddress] = useState({})
const handleAddressChange = async (field: string, value: string) => {
const newAddress = { ...address, [field]: value }
setAddress(newAddress)
if (field === 'state' || field === 'zip' || field === 'country') {
const newShipping = await calculateShippingCost(items, newAddress, selectedMethod)
onAddressChange(newAddress, newShipping)
}
}
return (
<form>
<input placeholder="State" onChange={(e) => handleAddressChange('state', e.target.value)} />
<input placeholder="Zip" onChange={(e) => handleAddressChange('zip', e.target.value)} />
<input placeholder="Country" onChange={(e) => handleAddressChange('country', e.target.value)} />
</form>
)
}
Debounce the async call by 300–500ms to avoid firing on every keystroke during zip entry.
ID: ecommerce-shipping-tax.shipping-calc.recalc-on-address-change
Severity: high
What to look for: Before evaluating, quote the checkout address form's onChange or onBlur handlers. List all address fields (state, zip, country) and classify whether each triggers a shipping recalculation call. Count: X of 3 address fields trigger recalculation.
Pass criteria: At least 2 of 3 address fields (state, zip, country) have onChange or onBlur handlers that invoke a shipping recalculation function, and the checkout summary UI updates the displayed shipping cost without requiring a full page reload.
Fail criteria: Fewer than 2 of 3 address fields trigger recalculation, or shipping cost only updates on page reload, or no address change handlers exist in the checkout form.
Skip (N/A) when: Shipping address is fixed (digital products only, in-store pickup only, or address is pre-filled from user profile with no edit option).
Detail on fail: "0 of 3 address fields trigger shipping recalculation. Changing state from CA to NY does not update the $8.99 shipping cost." or "State onChange exists but calls no recalculation function — handler is empty."
Cross-reference: Related to ecommerce-shipping-tax.checkout-integration.recalc-on-all-changes (both shipping and tax must recalculate) and ecommerce-shipping-tax.shipping-calc.rate-calculation-accuracy (recalculation depends on dynamic rate logic).
Remediation: Implement address change listeners with shipping recalculation in components/ShippingAddressForm.tsx:
// components/ShippingAddressForm.tsx
export function ShippingAddressForm({ onAddressChange }) {
const [address, setAddress] = useState({})
const handleAddressChange = async (field: string, value: string) => {
const newAddress = { ...address, [field]: value }
setAddress(newAddress)
if (field === 'state' || field === 'zip') {
const newShipping = await calculateShippingCost(items, newAddress, selectedMethod)
onAddressChange(newAddress, newShipping)
}
}
return (
<form className="space-y-2">
<input placeholder="State" onChange={(e) => handleAddressChange('state', e.target.value)} />
<input placeholder="Zip" onChange={(e) => handleAddressChange('zip', e.target.value)} />
</form>
)
}