From 5384608d3f0f80a1323ee885215ad4b116a4d0be Mon Sep 17 00:00:00 2001 From: Dharit Tantiviramanond Date: Tue, 31 Oct 2023 15:49:28 -0400 Subject: [PATCH 1/2] [PAY-2101] Cancel balance polling on purchase start --- packages/common/src/hooks/index.ts | 1 + packages/common/src/hooks/useInterval.ts | 26 +++++++++++++++++++ packages/common/src/hooks/useUSDCBalance.ts | 11 +++++--- .../hooks/usePurchaseContentFormState.ts | 9 ++++++- .../hooks/usePurchaseContentFormState.ts | 13 +++++++++- 5 files changed, 55 insertions(+), 5 deletions(-) create mode 100644 packages/common/src/hooks/useInterval.ts diff --git a/packages/common/src/hooks/index.ts b/packages/common/src/hooks/index.ts index d3fe067c899..3fd8f439720 100644 --- a/packages/common/src/hooks/index.ts +++ b/packages/common/src/hooks/index.ts @@ -23,3 +23,4 @@ export * from './useGeneratePlaylistArtwork' export * from './useUSDCBalance' export * from './purchaseContent' export * from './useAccessAndRemixSettings' +export * from './useInterval' diff --git a/packages/common/src/hooks/useInterval.ts b/packages/common/src/hooks/useInterval.ts new file mode 100644 index 00000000000..9865b804cd5 --- /dev/null +++ b/packages/common/src/hooks/useInterval.ts @@ -0,0 +1,26 @@ +import { useEffect, useRef } from 'react' + +export function useInterval(callback: () => void, delay: number | null) { + const savedCallback = useRef(callback) + const intervalId = useRef() + + // Remember the latest callback if it changes. + useEffect(() => { + savedCallback.current = callback + }, [callback]) + + // Set up the interval. + useEffect(() => { + // Don't schedule if no delay is specified. + // Note: 0 is a valid value for delay. + if (!delay && delay !== 0) { + return + } + + intervalId.current = setInterval(() => savedCallback.current(), delay) + + return () => clearInterval(intervalId.current) + }, [delay]) + + return intervalId.current +} diff --git a/packages/common/src/hooks/useUSDCBalance.ts b/packages/common/src/hooks/useUSDCBalance.ts index 364fae7032c..a58c5bc0afb 100644 --- a/packages/common/src/hooks/useUSDCBalance.ts +++ b/packages/common/src/hooks/useUSDCBalance.ts @@ -2,7 +2,6 @@ import { useCallback, useEffect, useState } from 'react' import BN from 'bn.js' import { useDispatch, useSelector } from 'react-redux' -import { useInterval } from 'react-use' import { Status } from 'models/Status' import { BNUSDC, StringUSDC } from 'models/Wallet' @@ -12,6 +11,8 @@ import { getRecoveryStatus } from 'store/buy-usdc/selectors' import { getUSDCBalance } from 'store/wallet/selectors' import { setUSDCBalance } from 'store/wallet/slice' +import { useInterval } from './useInterval' + /** * On mount, fetches the USDC balance for the current user and stores it * in the redux wallet slice. @@ -58,11 +59,15 @@ export const useUSDCBalance = ({ refresh() }, [refresh]) - useInterval(() => { + const id = useInterval(() => { if (isPolling) { refresh() } }, pollingInterval) - return { balanceStatus, recoveryStatus, data, refresh } + const cancelPolling = useCallback(() => { + clearInterval(id) + }, [id]) + + return { balanceStatus, recoveryStatus, data, refresh, cancelPolling } } diff --git a/packages/mobile/src/components/premium-track-purchase-drawer/hooks/usePurchaseContentFormState.ts b/packages/mobile/src/components/premium-track-purchase-drawer/hooks/usePurchaseContentFormState.ts index 5a872bda22b..dc00ee35b8d 100644 --- a/packages/mobile/src/components/premium-track-purchase-drawer/hooks/usePurchaseContentFormState.ts +++ b/packages/mobile/src/components/premium-track-purchase-drawer/hooks/usePurchaseContentFormState.ts @@ -20,7 +20,8 @@ export const usePurchaseContentFormState = ({ price }: { price: number }) => { const { data: currentBalance, recoveryStatus, - refresh + refresh, + cancelPolling } = useUSDCBalance({ isPolling: true }) // Refresh balance on successful recovery @@ -30,6 +31,12 @@ export const usePurchaseContentFormState = ({ price }: { price: number }) => { } }, [recoveryStatus, refresh]) + useEffect(() => { + if (isUnlocking) { + cancelPolling() + } + }, [isUnlocking, cancelPolling]) + const purchaseSummaryValues = usePurchaseSummaryValues({ price, currentBalance diff --git a/packages/web/src/components/premium-content-purchase-modal/hooks/usePurchaseContentFormState.ts b/packages/web/src/components/premium-content-purchase-modal/hooks/usePurchaseContentFormState.ts index 8f574de4b7a..1dc47fb7d4c 100644 --- a/packages/web/src/components/premium-content-purchase-modal/hooks/usePurchaseContentFormState.ts +++ b/packages/web/src/components/premium-content-purchase-modal/hooks/usePurchaseContentFormState.ts @@ -17,7 +17,12 @@ export const usePurchaseContentFormState = ({ price }: { price: number }) => { const error = useSelector(getPurchaseContentError) const isUnlocking = !error && isContentPurchaseInProgress(stage) - const { data: currentBalance, recoveryStatus, refresh } = useUSDCBalance() + const { + data: currentBalance, + recoveryStatus, + refresh, + cancelPolling + } = useUSDCBalance({ isPolling: true }) // Refresh balance on successful recovery useEffect(() => { @@ -31,6 +36,12 @@ export const usePurchaseContentFormState = ({ price }: { price: number }) => { currentBalance }) + useEffect(() => { + if (isUnlocking) { + cancelPolling() + } + }, [isUnlocking, cancelPolling]) + return { stage, error, From 6a1b8c993e55cef2bf1a959e23454c56b98f65ef Mon Sep 17 00:00:00 2001 From: Dharit Tantiviramanond Date: Tue, 31 Oct 2023 15:50:50 -0400 Subject: [PATCH 2/2] isomorphic --- packages/common/src/hooks/useInterval.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/common/src/hooks/useInterval.ts b/packages/common/src/hooks/useInterval.ts index 9865b804cd5..1f655a27e6e 100644 --- a/packages/common/src/hooks/useInterval.ts +++ b/packages/common/src/hooks/useInterval.ts @@ -1,11 +1,13 @@ import { useEffect, useRef } from 'react' +import { useIsomorphicLayoutEffect } from 'react-use' + export function useInterval(callback: () => void, delay: number | null) { const savedCallback = useRef(callback) const intervalId = useRef() // Remember the latest callback if it changes. - useEffect(() => { + useIsomorphicLayoutEffect(() => { savedCallback.current = callback }, [callback])