Skip to content
This repository has been archived by the owner on Nov 10, 2023. It is now read-only.

Commit

Permalink
Fix: avoid loading safe multiple times
Browse files Browse the repository at this point in the history
Lint
  • Loading branch information
katspaugh committed Dec 1, 2021
1 parent 7096bdc commit 918d68e
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 53 deletions.
4 changes: 2 additions & 2 deletions src/components/App/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ const App: React.FC = ({ children }) => {
const currentCurrency = useSelector(currentCurrencySelector)
const granted = useSelector(grantedSelector)
const sidebarItems = useSidebarItems()
const safeLoaded = useLoadSafe(addressFromUrl)
const dispatch = useDispatch()
useSafeScheduledUpdates(safeLoaded, addressFromUrl)
useLoadSafe(addressFromUrl) // load initially
useSafeScheduledUpdates(addressFromUrl) // load every X seconds
useAddressBookSync()

const sendFunds = safeActionsState.sendFunds
Expand Down
32 changes: 10 additions & 22 deletions src/logic/safe/hooks/useLoadSafe.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,25 @@
import { useEffect, useState } from 'react'
import { useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'

import addViewedSafe from 'src/logic/currentSession/store/actions/addViewedSafe'
import fetchLatestMasterContractVersion from 'src/logic/safe/store/actions/fetchLatestMasterContractVersion'
import { fetchSafe } from 'src/logic/safe/store/actions/fetchSafe'
import fetchTransactions from 'src/logic/safe/store/actions/transactions/fetchTransactions'
import { Dispatch } from 'src/logic/safe/store/actions/types.d'
import { updateAvailableCurrencies } from 'src/logic/currencyValues/store/actions/updateAvailableCurrencies'
import { currentChainId } from 'src/logic/config/store/selectors'
import { fetchSafeTokens } from 'src/logic/tokens/store/actions/fetchSafeTokens'

export const useLoadSafe = (safeAddress?: string): boolean => {
export const useLoadSafe = (safeAddress?: string): void => {
const dispatch = useDispatch<Dispatch>()
const chainId = useSelector(currentChainId)
const [isSafeLoaded, setIsSafeLoaded] = useState(false)

useEffect(() => {
setIsSafeLoaded(false)
}, [safeAddress])
if (!safeAddress) return

useEffect(() => {
const fetchData = async () => {
if (safeAddress) {
await dispatch(fetchLatestMasterContractVersion())
await dispatch(fetchSafe(safeAddress, isSafeLoaded))

setIsSafeLoaded(true)
await dispatch(updateAvailableCurrencies())
await dispatch(fetchTransactions(chainId, safeAddress))
dispatch(addViewedSafe(safeAddress))
}
}
fetchData()
}, [chainId, dispatch, safeAddress, isSafeLoaded])

return isSafeLoaded
dispatch(fetchLatestMasterContractVersion())
dispatch(fetchSafe(safeAddress))
dispatch(fetchSafeTokens(safeAddress))
dispatch(updateAvailableCurrencies())
dispatch(addViewedSafe(safeAddress))
}, [dispatch, safeAddress, chainId])
}
37 changes: 15 additions & 22 deletions src/logic/safe/hooks/useSafeScheduledUpdates.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,26 @@
import { useEffect, useRef } from 'react'
import { useDispatch } from 'react-redux'
import { useEffect, useState } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { currentChainId } from 'src/logic/config/store/selectors'
import { fetchSafe } from 'src/logic/safe/store/actions/fetchSafe'
import { fetchSafeTokens } from 'src/logic/tokens/store/actions/fetchSafeTokens'
import { TIMEOUT } from 'src/utils/constants'
import { SAFE_POLLING_INTERVAL } from 'src/utils/constants'

export const useSafeScheduledUpdates = (safeLoaded: boolean, safeAddress?: string): void => {
export const useSafeScheduledUpdates = (safeAddress?: string): void => {
const dispatch = useDispatch()
const timer = useRef<number>()
const [pollCount, setPollCount] = useState<number>(0)
const chainId = useSelector(currentChainId)

useEffect(() => {
// using this variable to prevent setting a timeout when the component is already unmounted or the effect
// has to run again
let mounted = true
const fetchSafeData = (address: string): void => {
dispatch(fetchSafe(address, safeLoaded))
dispatch(fetchSafeTokens(address))

if (mounted) {
timer.current = window.setTimeout(() => fetchSafeData(address), TIMEOUT * 3)
const timer = setTimeout(() => {
if (safeAddress) {
dispatch(fetchSafe(safeAddress))
dispatch(fetchSafeTokens(safeAddress))
}
}

if (safeAddress && safeLoaded) {
fetchSafeData(safeAddress)
}
setPollCount((prev) => prev + 1)
}, SAFE_POLLING_INTERVAL)

return () => {
mounted = false
clearTimeout(timer.current)
clearTimeout(timer)
}
}, [dispatch, safeAddress, safeLoaded])
}, [dispatch, safeAddress, chainId, pollCount, setPollCount])
}
7 changes: 3 additions & 4 deletions src/logic/safe/store/actions/fetchSafe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,9 @@ export const buildSafe = async (safeAddress: string): Promise<SafeRecordProps> =
* @note It's being used by the app when it loads for the first time and for the Safe's data polling
*
* @param {string} safeAddress
* @param {boolean} isSafeLoaded
*/
export const fetchSafe =
(safeAddress: string, isSafeLoaded = false) =>
(safeAddress: string) =>
async (dispatch: Dispatch<any>): Promise<Action<Partial<SafeRecordProps>> | void> => {
let address = ''
try {
Expand Down Expand Up @@ -95,11 +94,11 @@ export const fetchSafe =
const shouldUpdateTxHistory = txHistoryTag !== safeInfo.txHistoryTag
const shouldUpdateTxQueued = txQueuedTag !== safeInfo.txQueuedTag

if (shouldUpdateCollectibles || !isSafeLoaded) {
if (shouldUpdateCollectibles) {
dispatch(fetchCollectibles(safeAddress))
}

if (shouldUpdateTxHistory || shouldUpdateTxQueued || !isSafeLoaded) {
if (shouldUpdateTxHistory || shouldUpdateTxQueued) {
dispatch(fetchTransactions(getNetworkId(), safeAddress))
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/routes/safe/components/Apps/components/AppFrame.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {
import { isSameURL } from 'src/utils/url'
import { useAnalytics, SAFE_EVENTS } from 'src/utils/googleAnalytics'
import { LoadingContainer } from 'src/components/LoaderContainer/index'
import { TIMEOUT } from 'src/utils/constants'
import { SAFE_POLLING_INTERVAL } from 'src/utils/constants'
import { ConfirmTxModal } from './ConfirmTxModal'
import { useIframeMessageHandler } from '../hooks/useIframeMessageHandler'
import { getAppInfoFromUrl, getEmptySafeApp } from '../utils'
Expand Down Expand Up @@ -117,7 +117,7 @@ const AppFrame = ({ appUrl }: Props): ReactElement => {
if (appIsLoading) {
timer.current = window.setTimeout(() => {
setIsLoadingSlow(true)
}, TIMEOUT)
}, SAFE_POLLING_INTERVAL)
errorTimer.current = window.setTimeout(() => {
setAppLoadError(() => {
throw Error(APP_LOAD_ERROR)
Expand Down
2 changes: 1 addition & 1 deletion src/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const SAFE_APPS_RPC_TOKEN = process.env.REACT_APP_SAFE_APPS_RPC_INFURA_TO
export const LATEST_SAFE_VERSION = process.env.REACT_APP_LATEST_SAFE_VERSION || '1.3.0'
export const APP_VERSION = process.env.REACT_APP_APP_VERSION || 'not-defined'
export const COLLECTIBLES_SOURCE = process.env.REACT_APP_COLLECTIBLES_SOURCE || 'Gnosis'
export const TIMEOUT = process.env.NODE_ENV === 'test' ? 1500 : 5000
export const SAFE_POLLING_INTERVAL = process.env.NODE_ENV === 'test' ? 4500 : 15000
export const ETHERSCAN_API_KEY = process.env.REACT_APP_ETHERSCAN_API_KEY || ''
export const ETHGASSTATION_API_KEY = process.env.REACT_APP_ETHGASSTATION_API_KEY
export const CONFIG_SERVICE_URL =
Expand Down

0 comments on commit 918d68e

Please sign in to comment.