Skip to content

fix(billing): Prevent checkout form resetting when payment details are updated#110681

Draft
dashed wants to merge 3 commits intomasterfrom
billing/BIL-2186
Draft

fix(billing): Prevent checkout form resetting when payment details are updated#110681
dashed wants to merge 3 commits intomasterfrom
billing/BIL-2186

Conversation

@dashed
Copy link
Member

@dashed dashed commented Mar 13, 2026

Summary

  • Fix checkout form silently resetting from Team to Business when users save payment details during checkout
  • Add comprehensive tests for plan selection persistence across subscription store updates

Problem

When a free/trial user selects the Team plan during checkout and then saves their credit card, the plan selection silently resets to Business. Multiple customers reported being charged for the wrong plan.

Root cause: PR #105861 converted AMCheckout from a class component to a function component. The old componentDidUpdate only re-fetched billing config when checkoutTier changed. The new useEffect includes fetchBillingConfig in its dependency array, whose identity changes on every subscription prop update (via SubscriptionStore). This causes the effect to re-run fetchBillingConfig(), which re-initializes form data with the default Business plan for free/trial users.

Fix

Two complementary defenses:

  1. Ref guard (isFormInitialized): Inside fetchBillingConfig, form data initialization is wrapped in a ref guard that prevents re-initialization after the first successful load
  2. Stable useEffect deps: The fetch effect dependency array is changed to [subscription.canSelfServe, checkoutTier] (primitives only), matching the original class component's componentDidUpdate behavior

Follows React best practices:

Test plan

  • New test: free user selects Team → subscription store update → Team preserved
  • New test: trial user selects Team → subscription store update → Team preserved
  • New test: multiple rapid subscription store updates → form data preserved
  • All 96 existing checkout tests pass (13 test suites)
  • Pre-commit (eslint, prettier, stylelint) passes

Closes https://linear.app/getsentry/issue/BIL-2186/checkout-form-resets-plan-when-payment-details-are-entered

dashed added 2 commits March 13, 2026 16:19
When a free/trial user selects the Team plan during checkout and then
saves their credit card, the plan selection silently resets to Business.

Root cause: PR #105861 converted AMCheckout from a class component to a
function component. The old componentDidUpdate only re-fetched billing
config when checkoutTier changed. The new useEffect includes
fetchBillingConfig in its dependency array, whose identity changes on
every subscription prop update (via SubscriptionStore). This causes the
effect to re-run fetchBillingConfig(), which re-initializes form data
with the default Business plan for free/trial users.

Fix: Two complementary defenses:
1. Add isFormInitialized ref guard inside fetchBillingConfig to prevent
   re-initialization of form data after the first successful load.
2. Stabilize the useEffect dependency array to [subscription.canSelfServe,
   checkoutTier], matching the original class component behavior.
Add tests verifying that the checkout form preserves the user's plan
selection when the subscription store updates (e.g. after saving
payment details).

Covers:
- Free user: select Team → subscription update → Team preserved
- Trial user: select Team → subscription update → Team preserved
- Multiple rapid subscription updates → form data preserved
@linear-code
Copy link

linear-code bot commented Mar 13, 2026

@github-actions github-actions bot added the Scope: Frontend Automatically applied to PRs that change frontend components label Mar 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Frontend Automatically applied to PRs that change frontend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant