Omit undefined optional props on AcceleratedCheckoutButtons - #521
Open
JoaoPauloCMarra wants to merge 2 commits into
Open
JoaoPauloCMarra wants to merge 2 commits into
JoaoPauloCMarra wants to merge 2 commits into
Conversation
Pass applePayLabel, applePayStyle, cornerRadius, and wallets to the native component only when they are defined, and omit height from the style until native reports a size, so undefined values are not serialized across the bridge where they can clobber kit defaults.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
applePayLabel,applePayStyle,cornerRadius, andwalletstoRCTAcceleratedCheckoutButtonsonly when they are defined, instead of always passing them (and thereforeundefined) to the native component.heightfrom the style until native reports a size viaonSizeChange, instead of forcingheight: undefinedinto the style on first render.Reproduction (3.9.0)
Render
AcceleratedCheckoutButtonswithout the optional props, e.g.:The wrapper renders the native component with
applePayLabel={undefined},applePayStyle={undefined},cornerRadius={undefined},wallets={undefined}, andstyle={{flex: 1, height: undefined}}. Theundefinedvalues are serialized across the JS→native bridge instead of the props simply being absent.Root cause
On the native side (iOS,
ios/AcceleratedCheckoutButtons.swift), the optional props are@objc var cornerRadius: NSNumber?,wallets: [String]?,applePayLabel: String?,applePayStyle: String?and the comment above them says the values are intentionallynilso that the kit defaults are used. The component relies on distinguishing "prop absent" from "prop present":walletsexplicitly provided and empty means render nothing (wallets != nil && shopifyWallets.isEmpty); when the prop is absent, the SDK decides the default wallets. Anundefined/nullvalue crossing the bridge does not reliably map to "absent", so the default-wallet fallback can be clobbered.applePayStyleis always funneled throughPayWithApplePayButtonStyle.from(applePayStyle)inupdateView(), so a value that arrives as an unexpected representation ofundefinedcan steer the Apple Pay button away from itsautomaticdefault styling.didSeton these props triggersupdateView()(and forwallets, an intrinsic-content-size invalidation), so explicitly serialized undefined values cause redundant native re-renders at mount.style: {...defaultStyles, height: undefined}forces an explicitundefinedheight into the Yoga style on first render instead of leaving the height unset untilonSizeChangereports one.Why the fix works
Spreading each optional prop only when it is defined (
{...(prop === undefined ? {} : {prop}})) keeps the prop absent from the element, which is the representation native already handles correctly as "use the kit default". The same idea applies toheight: whendynamicHeightisundefined, we passdefaultStyleswithout aheightkey rather thanheight: undefined.Testing
tests/AcceleratedCheckoutButtons.test.tsx:applePayLabel,applePayStyle,cornerRadius, andwalletsfrom the native element when not providedheightfrom the style untilonSizeChangefires (existing test already covers that the reported height is then applied)pnpm test— 125 tests, 6 suites, all passingpnpm lintinmodules/@shopify/checkout-sheet-kit(typecheck + eslint) — passingRelationship to #515 / #502
This PR intentionally does not touch
flex: 1/ hit-area behavior — that is covered by #515 (fixes #502). The changes here are complementary: #515 makes the reported native height participate in layout, while this PR stops undefined props (including an explicitundefinedheight) from being serialized across the bridge at mount. If both land, thestyleline will need a trivial merge.