feat: persist user input values when selected payment method is changed - #1692
feat: persist user input values when selected payment method is changed#1692Shivam25092001 wants to merge 5 commits into
Conversation
|
[should-fix] Recompute |
02cdcf1 to
34da08a
Compare
| // local state), so they're seeded through that path, not the persistence cache. | ||
| let isPersistableRenderType = field => | ||
| switch field.fieldRenderType { | ||
| | Country | PhoneCountryCode => false |
There was a problem hiding this comment.
Could you please explain why PhoneCountryCode and Country are marked as false
There was a problem hiding this comment.
They are being maintained already by userCountry atom.
There was a problem hiding this comment.
Also, PhoneCountryCode is excluded because its dropdown is controlled by component-local state (valueDropDown)
There was a problem hiding this comment.
Removed isPersistableRenderType entirely to simplify the logic.
Description:
-
CountryDropdownFieldderives the rendered country fromfield.input.value(storedIso), falling back to theuserCountryatom only when RFF is empty, and pushes the effective value back into the atom via an effect. Since RFF is the display source of truth, replaying the cached user value into initialValues before the field re-registers is enough to restore the pick — the atom path is just a fallback, not a competing owner. -
PhoneCountryCodeDropdownFieldhas the paired fix: The component rebuilds that UI value fromfield.input.value(storedCode) so a cached dial code survives the remount.
With both fields reading from RFF, the generic persistence path works for them the same way it works for every other dynamic field.
|
Can you also please add a use case of Update Intent flow with these new changes in the PR description? |
Screen.Recording.2026-08-12.at.3.17.59.PM.mov |
|
973f82d
Type of Change
Description
Persists user-entered dynamic field values when the selected payment method type changes, so a shopper who types into shared fields (name, email, phone, address, etc.) doesn't lose that input after switching payment methods.
Why this happens:
In
PaymentElement.resthe payment-method subtree is rendered under<ErrorBoundary key={selectedOption} ...>. Switching the payment method type changes the key and remounts the whole subtree (DynamicFields →ReactFinalForm.Form), destroying all form state. Previously only Country survived, because it round-trips through the persistentuserCountryatom.Changes:
userDynamicFieldsValues : Dict.t<string>inRecoilAtoms.res, keyed byconfirmRequestWritePath. It lives above the remount boundary, so its contents survive the payment-method switch.FormBody'sonFormChange, the typed values of persistable fields are written into the atom every time the form updates.initialValuesWithUserInputOverridememo seeds the form'sinitialValuesfrom the cached atom (layered on top of the existing billing-details override), and the ReactFinalForm.Form now consumes this override.persistableFieldsset — the fields whose values we persist. UnlikemissingRequiredFieldsFiltered(which dedups Email/CardHolderName down to the single visible input), this keeps both name paths (first_name+last_name) and every email path, since the combined name/email inputs write all of them into RFF. It excludes self-managed fields (Country/PhoneCountryCode), which own their value outside RFF and are seeded through their own atom/local-state path.missingRequiredFieldsFilteredfilter into a singlerendersVisibleInputhelper, reused by bothmissingRequiredFieldsFilteredandpersistableFields.No change to the '/confirm' payload shape — seeding stays restricted to the current payment method's rendered fields.
How did you test it?
Manually verified in the SDK: entered values into shared dynamic fields (name / email / phone / address), switched between payment method types, and confirmed the previously typed values are restored on the re-rendered form instead of being wiped.
Screen.Recording.2026-08-06.at.6.18.32.PM.mov
Checklist