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..1f655a27e6e --- /dev/null +++ b/packages/common/src/hooks/useInterval.ts @@ -0,0 +1,28 @@ +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. + useIsomorphicLayoutEffect(() => { + 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,