From ffea0598cd2bd6467913f58eeb48fd4b80c80869 Mon Sep 17 00:00:00 2001 From: Vrishab Srivatsa <136090360+vsrivatsa-juspay@users.noreply.github.com> Date: Tue, 13 Feb 2024 17:42:48 +0530 Subject: [PATCH] Fix/semiloaded state race condition (#163) --- src/Components/DynamicFields.res | 46 ++++++++++++++++++---------- src/LoaderController.res | 20 +++++------- src/PaymentElement.res | 3 +- src/Utilities/DynamicFieldsUtils.res | 3 +- 4 files changed, 39 insertions(+), 33 deletions(-) diff --git a/src/Components/DynamicFields.res b/src/Components/DynamicFields.res index 979168ace..bf2e89de3 100644 --- a/src/Components/DynamicFields.res +++ b/src/Components/DynamicFields.res @@ -21,7 +21,7 @@ let make = ( let {billingAddress} = Recoil.useRecoilValueFromAtom(optionAtom) //<...>// - let paymentMethodTypes = + let paymentMethodTypes = React.useMemo3(() => { PaymentMethodsRecord.getPaymentMethodTypeFromList( ~list, ~paymentMethod, @@ -30,19 +30,25 @@ let make = ( ~paymentMethodName=paymentMethodType, ), )->Belt.Option.getWithDefault(PaymentMethodsRecord.defaultPaymentMethodType) + }, (list, paymentMethod, paymentMethodType)) - let requiredFieldsWithBillingDetails = if paymentMethod === "card" { - paymentMethodTypes.required_fields - } else if ( - PaymentMethodsRecord.dynamicFieldsEnabledPaymentMethods->Js.Array2.includes(paymentMethodType) - ) { - paymentMethodTypes.required_fields - } else { - [] - } + let requiredFieldsWithBillingDetails = React.useMemo3(() => { + if paymentMethod === "card" { + paymentMethodTypes.required_fields + } else if ( + PaymentMethodsRecord.dynamicFieldsEnabledPaymentMethods->Js.Array2.includes(paymentMethodType) + ) { + paymentMethodTypes.required_fields + } else { + [] + } + }, (paymentMethod, paymentMethodTypes.required_fields, paymentMethodType)) - let requiredFields = - requiredFieldsWithBillingDetails->DynamicFieldsUtils.removeBillingDetailsIfUseBillingAddress + let requiredFields = React.useMemo1(() => { + requiredFieldsWithBillingDetails->DynamicFieldsUtils.removeBillingDetailsIfUseBillingAddress( + billingAddress, + ) + }, [requiredFieldsWithBillingDetails]) let isAllStoredCardsHaveName = React.useMemo1(() => { PaymentType.getIsAllStoredCardsHaveName(savedCards) @@ -265,24 +271,30 @@ let make = ( } } - let dynamicFieldsToRenderOutsideBilling = + let dynamicFieldsToRenderOutsideBilling = React.useMemo1(() => { fieldsArr->Js.Array2.filter(field => field->DynamicFieldsUtils.isFieldTypeToRenderOutsideBilling ) + }, [fieldsArr]) - let dynamicFieldsToRenderInsideBilling = + let dynamicFieldsToRenderInsideBilling = React.useMemo1(() => { fieldsArr->Js.Array2.filter(field => !(field->DynamicFieldsUtils.isFieldTypeToRenderOutsideBilling) ) + }, [fieldsArr]) - let isInfoElementPresent = dynamicFieldsToRenderInsideBilling->Js.Array2.includes(InfoElement) + let isInfoElementPresent = React.useMemo1(() => { + dynamicFieldsToRenderInsideBilling->Js.Array2.includes(InfoElement) + }, [dynamicFieldsToRenderInsideBilling]) - let isOnlyInfoElementPresent = + let isOnlyInfoElementPresent = React.useMemo2(() => { dynamicFieldsToRenderInsideBilling->Js.Array2.length === 1 && isInfoElementPresent + }, (dynamicFieldsToRenderInsideBilling, isInfoElementPresent)) - let isRenderDynamicFieldsInsideBilling = + let isRenderDynamicFieldsInsideBilling = React.useMemo2(() => { dynamicFieldsToRenderInsideBilling->Js.Array2.length > 0 && (dynamicFieldsToRenderInsideBilling->Js.Array2.length > 1 || !isOnlyInfoElementPresent) + }, (dynamicFieldsToRenderInsideBilling, isOnlyInfoElementPresent)) React.useEffect1(() => { let fieldsArrStr = fieldsArr->Js.Array2.map(field => { diff --git a/src/LoaderController.res b/src/LoaderController.res index 955211b86..abee9d6a1 100644 --- a/src/LoaderController.res +++ b/src/LoaderController.res @@ -125,6 +125,14 @@ let make = (~children, ~paymentMode, ~setIntegrateErrorError, ~logger) => { handlePostMessage([("iframeMounted", true->Js.Json.boolean)]) handlePostMessage([("applePayMounted", true->Js.Json.boolean)]) logger.setLogInitiated() + switch paymentlist { + | Loaded(_) + | LoadError(_) => () + | _ => + setList(._ => + showCardFormByDefault && Utils.checkPriorityList(paymentMethodOrder) ? SemiLoaded : Loading + ) + } Window.addEventListener("click", ev => handleOnClickPostMessage(~targetOrigin=keys.parentURL, ev) ) @@ -358,18 +366,6 @@ let make = (~children, ~paymentMode, ~setIntegrateErrorError, ~logger) => { handleMessage(handleFun, "Error in parsing sent Data") }, (showCardFormByDefault, paymentMethodOrder)) - React.useEffect1(() => { - switch paymentlist { - | Loaded(_) - | LoadError(_) => () - | _ => - setList(._ => - showCardFormByDefault && Utils.checkPriorityList(paymentMethodOrder) ? SemiLoaded : Loading - ) - } - None - }, [paymentlist]) - let observer = ResizeObserver.newResizerObserver(entries => { entries ->Js.Array2.map(item => { diff --git a/src/PaymentElement.res b/src/PaymentElement.res index 3d189bccf..1e8240830 100644 --- a/src/PaymentElement.res +++ b/src/PaymentElement.res @@ -20,7 +20,6 @@ let make = ( ) let isApplePayReady = Recoil.useRecoilValueFromAtom(isApplePayReady) let isGooglePayReady = Recoil.useRecoilValueFromAtom(isGooglePayReady) - let pmList = Recoil.useRecoilValueFromAtom(list) let methodslist = Recoil.useRecoilValueFromAtom(list) let paymentOrder = paymentMethodOrder->Utils.getOptionalArr->Utils.removeDuplicate let (sessions, setSessions) = React.useState(_ => Js.Dict.empty()->Js.Json.object_) @@ -319,7 +318,7 @@ let make = ( - {switch pmList { + {switch methodslist { | LoadError(_) => React.null | _ => , + billingAddress: PaymentType.billingAddress, ) => { - let {billingAddress} = Recoil.useRecoilValueFromAtom(RecoilAtoms.optionAtom) - if billingAddress.isUseBillingAddress { requiredFields->Js.Array2.filter(requiredField => { !(requiredField.field_type->isBillingAddressFieldType)