Skip to content

Payment components refactoring — deprecate containers, introduce standalone components #795

@acasazza

Description

@acasazza

Context

The payment_gateways, payment_methods, payment_source folders, and the order checkout flow components currently follow the container pattern: a *Container component owns state and provides it via context, while inner components consume that context.

This is the same pattern already refactored for address components (see standalone address forms). The goal is to apply the same approach here.

Current structure

payment_methods/
  PaymentMethodsContainer.tsx   ← owns state, provides PaymentMethodContext
  PaymentMethod.tsx / PaymentMethodName.tsx / PaymentMethodPrice.tsx

payment_gateways/
  PaymentGateway.tsx            ← gateway dispatcher, reads PaymentMethodContext
  AdyenGateway.tsx / BraintreeGateway.tsx / CheckoutComGateway.tsx / ...

payment_source/
  PaymentSource.tsx             ← reads PaymentMethodChildrenContext
  AdyenPayment.tsx / BraintreePayment.tsx / CheckoutComPayment.tsx / ...

orders/
  PlaceOrderContainer.tsx       ← owns place-order state, provides PlaceOrderContext
  PlaceOrderButton.tsx          ← reads PlaceOrderContext
  PrivacyAndTermsCheckbox.tsx   ← reads PlaceOrderContext

Goal

Refactor following the same pattern used for standalone address components:

  • Extract data-fetching and business logic into core functions and/or hooks (e.g. usePaymentMethods, usePlaceOrder)
  • Each component becomes self-contained — it accepts props directly and does not require a wrapping *Container to work
  • Deprecate container-pattern components with a JSDoc @deprecated notice pointing to the new API
  • Keep deprecated containers in this release for backwards compatibility

Implementation plan

Phase 1 — PaymentMethod (completed ✅)

  • Created usePlaceOrder hook encapsulating place-order state
  • PaymentMethod is now standalone (no PaymentMethodsContainer required)

Phase 2 — PlaceOrderButton, PlaceOrderContainer, PrivacyAndTermsCheckbox (completed ✅)

  • Created usePlaceOrder hook encapsulating place-order state
  • PlaceOrderButton is now standalone (accepts options prop directly)
  • PrivacyAndTermsCheckbox dispatches a DOM event (cl:placeorder:recheck) for sibling communication
  • Deprecated PlaceOrderContainer with @deprecated JSDoc
  • 100% test coverage for all new code

Phase 3 — Payment gateways/source (upcoming)

  • Extract usePaymentMethods / usePaymentSource hooks
  • Refactor each gateway and payment-source component
  • Deprecate PaymentMethodsContainer

References

  • Pattern already applied to: address standalone forms (AddressForm, BillingAddressForm, ShippingAddressForm)
  • Related infinite re-render fixes — some were caused by the container anti-pattern itself

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions