Skip to content

refactor: recoil to jotai migration#1416

Open
sh-iv-am wants to merge 2 commits intomainfrom
jotai
Open

refactor: recoil to jotai migration#1416
sh-iv-am wants to merge 2 commits intomainfrom
jotai

Conversation

@sh-iv-am
Copy link
Copy Markdown
Contributor

Type of Change

  • Bugfix
  • New feature
  • Enhancement
  • Refactoring
  • Dependency updates
  • Documentation
  • CI/CD

Description

Recoil to Jotai migration

How did you test it?

In example app with React 19

Checklist

  • I ran npm run re:build
  • I reviewed submitted code
  • I added unit tests for my changes where possible

@semanticdiff-com
Copy link
Copy Markdown

semanticdiff-com bot commented Mar 12, 2026

Review changes with  SemanticDiff

Changed Files
File Status
  Hyperswitch-React-Demo-App/package-lock.json  43% smaller
  rescript.json  33% smaller
  Hyperswitch-React-Demo-App/package.json  22% smaller
  package-lock.json  3% smaller
  package.json  0% smaller
  src/App.res Unsupported file format
  src/CardSchemeComponent.res Unsupported file format
  src/CardTheme.res Unsupported file format
  src/CollectWidget.res Unsupported file format
  src/Components/Accordion.res Unsupported file format
  src/Components/AccordionContainer.res Unsupported file format
  src/Components/AddBankAccount.res Unsupported file format
  src/Components/AddressPaymentInput.res Unsupported file format
  src/Components/BillingNamePaymentInput.res Unsupported file format
  src/Components/BlikCodePaymentInput.res Unsupported file format
  src/Components/Block.res Unsupported file format
  src/Components/ClickToPayAuthenticate.res Unsupported file format
  src/Components/ClickToPayDetails.res Unsupported file format
  src/Components/ClickToPayNotYou.res Unsupported file format
  src/Components/ClickToPayUiComponents.res Unsupported file format
  src/Components/CryptoCurrencyNetworks.res Unsupported file format
  src/Components/DocumentNumberInput.res Unsupported file format
  src/Components/DropdownField.res Unsupported file format
  src/Components/DynamicFields.res Unsupported file format
  src/Components/EmailPaymentInput.res Unsupported file format
  src/Components/ErrorComponent.res Unsupported file format
  src/Components/FullNamePaymentInput.res Unsupported file format
  src/Components/GiftCardNumberInput.res Unsupported file format
  src/Components/GiftCardPinInput.res Unsupported file format
  src/Components/InfoElement.res Unsupported file format
  src/Components/Input.res Unsupported file format
  src/Components/InputField.res Unsupported file format
  src/Components/LoaderPaymentShimmer.res Unsupported file format
  src/Components/ManageSavedItem.res Unsupported file format
  src/Components/Modal.res Unsupported file format
  src/Components/NicknamePaymentInput.res Unsupported file format
  src/Components/Or.res Unsupported file format
  src/Components/PayNowButton.res Unsupported file format
  src/Components/PaymentDropDownField.res Unsupported file format
  src/Components/PaymentElementShimmer.res Unsupported file format
  src/Components/PaymentField.res Unsupported file format
  src/Components/PaymentInputField.res Unsupported file format
  src/Components/PaymentShimmer.res Unsupported file format
  src/Components/PhoneNumberPaymentInput.res Unsupported file format
  src/Components/PixPaymentInput.res Unsupported file format
  src/Components/PortalCapture.res Unsupported file format
  src/Components/PoweredBy.res Unsupported file format
  src/Components/SaveDetailsCheckbox.res Unsupported file format
  src/Components/SavedCardItem.res Unsupported file format
  src/Components/SavedMethodItemV2.res Unsupported file format
  src/Components/SavedMethods.res Unsupported file format
  src/Components/SavedMethodsV2.res Unsupported file format
  src/Components/SessionPaymentWrapper.res Unsupported file format
  src/Components/Spinner.res Unsupported file format
  src/Components/Surcharge.res Unsupported file format
  src/Components/SurchargeUtils.res Unsupported file format
  src/Components/SwitchViewButton.res Unsupported file format
  src/Components/Terms.res Unsupported file format
  src/Components/VpaIdPaymentInput.res Unsupported file format
  src/FormViewJourney.res Unsupported file format
  src/FormViewTabs.res Unsupported file format
  src/Hooks/ClickToPayHook.res Unsupported file format
  src/Hooks/CommonCardProps.res Unsupported file format
  src/Hooks/CustomPaymentMethodsConfig.res Unsupported file format
  src/Hooks/ThirdPartyFlowHelpers.res Unsupported file format
  src/Hooks/UtilityHooks.res Unsupported file format
  src/Index.res Unsupported file format
  src/LoaderController.res Unsupported file format
  src/Payment.res Unsupported file format
  src/PaymentElement.res Unsupported file format
  src/PaymentElementRenderer.res Unsupported file format
  src/PaymentElementV2.res Unsupported file format
  src/PaymentManagement.res Unsupported file format
  src/PaymentMethodCollectElement.res Unsupported file format
  src/PaymentOptions.res Unsupported file format
  src/Payments/ACHBankDebit.res Unsupported file format
  src/Payments/ACHBankTransfer.res Unsupported file format
  src/Payments/AddBankDetails.res Unsupported file format
  src/Payments/ApplePay.res Unsupported file format
  src/Payments/BacsBankDebit.res Unsupported file format
  src/Payments/BacsBankTransfer.res Unsupported file format
  src/Payments/BankDebitModal.res Unsupported file format
  src/Payments/BecsBankDebit.res Unsupported file format
  src/Payments/Boleto.res Unsupported file format
  src/Payments/CardPayment.res Unsupported file format
  src/Payments/DateOfBirth.res Unsupported file format
  src/Payments/GPay.res Unsupported file format
  src/Payments/InstantBankTransfer.res Unsupported file format
  src/Payments/InstantBankTransferFinland.res Unsupported file format
  src/Payments/InstantBankTransferPoland.res Unsupported file format
  src/Payments/KlarnaCheckout.res Unsupported file format
  src/Payments/KlarnaSDK.res Unsupported file format
  src/Payments/PayPal.res Unsupported file format
  src/Payments/PaymentMethodsWrapper.res Unsupported file format
  src/Payments/PaymentRequestButtonElement.res Unsupported file format
  src/Payments/PaypalSDK.res Unsupported file format
  src/Payments/PaypalSDKHelpers.res Unsupported file format
  src/Payments/PazeButton.res Unsupported file format
  src/Payments/QRCodeDisplay.res Unsupported file format
  src/Payments/SamsungPayComponent.res Unsupported file format
  src/Payments/SavedMethodsWithPaymentForm.res Unsupported file format
  src/Payments/SepaBankDebit.res Unsupported file format
  src/Payments/SepaBankTransfer.res Unsupported file format
  src/Payments/ThreeDSRedirectionModal.res Unsupported file format
  src/Payments/VoucherDisplay.res Unsupported file format
  src/RenderPaymentMethods.res Unsupported file format
  src/SingleLineCardPayment.res Unsupported file format
  src/TabCard.res Unsupported file format
  src/Types/JotaiAtomTypes.res Unsupported file format
  src/Utilities/ApplePayHelpers.res Unsupported file format
  src/Utilities/DynamicFieldsUtils.res Unsupported file format
  src/Utilities/GooglePayHelpers.res Unsupported file format
  src/Utilities/JotaiAtoms.res Unsupported file format
  src/Utilities/JotaiAtomsV2.res Unsupported file format
  src/Utilities/PaymentHelpers.res Unsupported file format
  src/Utilities/PaymentHelpersV2.res Unsupported file format
  src/Utilities/PaymentUtils.res Unsupported file format
  src/Utilities/PaymentUtilsV2.res Unsupported file format
  src/Utilities/RecoilAtoms.res Unsupported file format
  src/Utilities/RecoilAtomsV2.res Unsupported file format
  src/Utilities/SamsungPayHelpers.res Unsupported file format
  src/Utilities/Utils.res Unsupported file format
  src/WalletElement.res Unsupported file format
  src/hyper-loader/AuthenticationSessionMethods.res Unsupported file format
  src/hyper-loader/Elements.res Unsupported file format
  src/hyper-loader/Hyper.res Unsupported file format
  src/hyper-loader/LoaderPaymentElement.res Unsupported file format
  src/hyper-loader/PaymentMethodsManagementElements.res Unsupported file format
  src/hyper-loader/PaymentSession.res Unsupported file format
  src/hyper-log-catcher/ErrorBoundary.res Unsupported file format
  src/hyper-log-catcher/ReusableReactSuspense.res Unsupported file format
  src/libraries/Jotai.res Unsupported file format
  src/libraries/Recoil.res Unsupported file format
  src/libraries/recoil.js  0% smaller

@github-actions
Copy link
Copy Markdown
Contributor

🚫 Missing Linked Issue

Hi 👋 This pull request does not appear to be linked to any open issue yet.

Linking your PR to an issue helps keep the project tidy and ensures the issue is closed automatically.

✔️ How to fix this

  • Add a keyword like Fixes #123 or Closes #456 to your PR description or a commit message.
  • Or link it manually using the "Linked issues" panel in the PR sidebar.

Tip: You can link multiple issues.
🚫 Note: If only one issue is linked, it must be open for this check to pass.

Once linked, this check will pass automatically on your next push or when you re-run the workflow.

Thanks for helping maintainers! 🙌

"@juspay-tech/hyper-js": "^1.7.2",
"@juspay-tech/react-hyper-js": "^1.2.4",
"@juspay-tech/hyper-js": "^2.1.0",
"@juspay-tech/react-hyper-js": "git@github.com:juspay/react-hyper-js.git",
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added this as published version of react-hyper-js is not compatible with react 19

let supportedCardBrands = React.useMemo(() => {
paymentMethodListValue->PaymentUtils.getSupportedCardBrands
}, paymentMethodListValue)
}, [paymentMethodListValue])
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ArushKapoorJuspay was it intentional?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so, it should never be outside of parentheses

}

let rec transformKeysWithoutModifyingValue = (json: JSON.t, to: case) => {
let transformKeysWithoutModifyingValue = (json: JSON.t, to: case) => {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of removing rec, it should call transformKeysWithoutModifyingValue inside instead of transformKeys

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about functionality but getting Rescript compilation warning because of it.

@sh-iv-am
Copy link
Copy Markdown
Contributor Author

Issues Found

1. Bug — SavedMethodsV2.res useEffect dependency array

In src/Components/SavedMethodsV2.res:186-192, the effect dependencies reference atom objects instead of atom values:

// new (incorrect)
}, (
  JotaiAtoms.areRequiredFieldsValid,  // ← this is an atom, not a bool
  isEmpty,
  complete,
  customerMethod,
  JotaiAtoms.isManualRetryEnabled,    // ← this is an atom, not a bool
))

// old — same issue existed via `open RecoilAtoms`
}, (areRequiredFieldsValid, isEmpty, complete, customerMethod, isManualRetryEnabled))

These should be local variables bound via Jotai.useAtomValue(...). Since atom references are stable module-level values (they never change), they have no effect as dependencies — the effect won't re-run when these values change. This is a pre-existing bug that the migration preserved rather than fixed.

2. Leftover commented-out code — LoaderController.res

  open JotaiAtoms
  // open JotaiAtomsV2    ← should be removed

The V2 atoms are accessed with full qualification (JotaiAtomsV2.paymentManagementList) elsewhere in the same file. The commented line is dead code.

3. useSetAtom binding only accepts updater functions

In src/libraries/Jotai.res:

external useSetAtom: atom<'value> => ('value => 'value) => unit = "useSetAtom"

The return type forces callers to use setFoo(_ => newValue) patterns. Jotai's actual API accepts newValue | (prev => newValue). This works but is a narrower binding than the real API. If any call site ever tries setFoo(newValue) directly, it'll be a type error. Worth documenting this constraint or widening the type.

4. Demo app uses a git SSH URL dependency

In Hyperswitch-React-Demo-App/package.json:

"@juspay-tech/react-hyper-js": "git@github.com:juspay/react-hyper-js.git"

This will fail for anyone without SSH access to that private repo. If this is temporary for testing, it should be reverted before merging. If it's a real change, it needs to be a published npm version.

5. RecoilAtomTypes module referenced in new code

src/Utilities/JotaiAtoms.res opens RecoilAtomTypes, and src/Components/PaymentField.res still has open RecoilAtomTypes. The module itself isn't changed (it's a shared types file), but the naming is confusing now that Recoil is gone. Consider renaming to AtomTypes or PaymentAtomTypes in a follow-up.

6. writableAtom type defined but unused

In Jotai.res:

type writableAtom<'value, 'args, 'result> = WritableAtom('value, 'args, 'result)

This appears unused in the diff. Either remove it or document what it's intended for.


Verdict

The migration is mechanically sound across all 100+ files, but there are a few things that should be addressed before merging — particularly the git SSH URL in the demo app (a potential CI/install blocker) and the SavedMethodsV2 useEffect deps bug (functional regression). The commented-out line and unused type are minor cleanup items.

@github-actions
Copy link
Copy Markdown
Contributor

🚫 Missing Linked Issue

Hi 👋 This pull request does not appear to be linked to any open issue yet.

Linking your PR to an issue helps keep the project tidy and ensures the issue is closed automatically.

✔️ How to fix this

  • Add a keyword like Fixes #123 or Closes #456 to your PR description or a commit message.
  • Or link it manually using the "Linked issues" panel in the PR sidebar.

Tip: You can link multiple issues.
🚫 Note: If only one issue is linked, it must be open for this check to pass.

Once linked, this check will pass automatically on your next push or when you re-run the workflow.

Thanks for helping maintainers! 🙌

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants