diff --git a/packages/page-parachains/src/Crowdloan/useContributions.ts b/packages/page-parachains/src/Crowdloan/useContributions.ts index ec53e9352d..101befd88a 100644 --- a/packages/page-parachains/src/Crowdloan/useContributions.ts +++ b/packages/page-parachains/src/Crowdloan/useContributions.ts @@ -7,7 +7,7 @@ import type { Balance, EventRecord, ParaId } from '@polkadot/types/interfaces'; import { useCallback, useEffect, useState } from 'react'; -import { useAccounts, useApi, useEventTrigger } from '@polkadot/react-hooks'; +import { useAccounts, useApi, useEventTrigger, useIsMountedRef } from '@polkadot/react-hooks'; import { encodeAddress } from '@polkadot/util-crypto'; interface Contributions { @@ -78,6 +78,7 @@ function extractDelta (api: ApiPromise, records: EventRecord[], { contributorsMa function useMyContributions (paraId: ParaId, childKey: string, keys: string[]): Record { const { api } = useApi(); const { allAccountsHex } = useAccounts(); + const mountedRef = useIsMountedRef(); const [state, setState] = useState>({}); const trigger = useEventTrigger([ @@ -94,21 +95,23 @@ function useMyContributions (paraId: ParaId, childKey: string, keys: string[]): if (trigger && keys.length) { Promise .all(keys.map((k) => api.rpc.childstate.getStorage(childKey, k))) - .then((values) => setState( - values - .map((v) => api.createType('Option', v)) - .map((o) => - o.isSome - ? api.createType('Balance', o.unwrap()) - : api.createType('Balance') - ) - .reduce((all, b, index) => ({ ...all, [keys[index]]: b }), {}) - )) + .then((values) => + mountedRef.current && setState( + values + .map((v) => api.createType('Option', v)) + .map((o) => + o.isSome + ? api.createType('Balance', o.unwrap()) + : api.createType('Balance') + ) + .reduce((all, b, index) => ({ ...all, [keys[index]]: b }), {}) + ) + ) .catch(console.error); } else { setState({}); } - }, [api, childKey, keys, trigger]); + }, [api, childKey, keys, mountedRef, trigger]); return state; } @@ -116,6 +119,7 @@ function useMyContributions (paraId: ParaId, childKey: string, keys: string[]): export default function useContributions (paraId: ParaId, childKey: string): Result { const { api } = useApi(); const { allAccountsHex } = useAccounts(); + const mountedRef = useIsMountedRef(); const [state, _setState] = useState(() => NO_CONTRIB); const myContributions = useMyContributions(paraId, childKey, state.myAccountsHex); @@ -164,11 +168,11 @@ export default function useContributions (paraId: ParaId, childKey: string): Res // first just adjust deltas useEffect((): void => { - triggerDelta && triggerDelta.events.length && + mountedRef.current && triggerDelta && triggerDelta.events.length && setState(triggerDelta.blockHash, (prev) => extractDelta(api, triggerDelta.events, prev, allAccountsHex, api.registry.chainSS58) ); - }, [api, allAccountsHex, setState, triggerDelta]); + }, [api, allAccountsHex, mountedRef, setState, triggerDelta]); // refreshing the whole map, all keys useEffect((): void => { @@ -176,12 +180,12 @@ export default function useContributions (paraId: ParaId, childKey: string): Res api.rpc.childstate .getKeys(childKey, '0x') .then((keys) => - setState(triggerAll.blockHash, (prev) => + mountedRef.current && setState(triggerAll.blockHash, (prev) => extractContributors(keys, prev, allAccountsHex, api.registry.chainSS58) ) ) .catch(console.error); - }, [allAccountsHex, api, childKey, setState, triggerAll]); + }, [allAccountsHex, api, childKey, mountedRef, setState, triggerAll]); // update when the contribution amounts have changed useEffect((): void => { diff --git a/packages/page-parachains/src/useFunds.ts b/packages/page-parachains/src/useFunds.ts index cd36edf81d..ed2356c8fa 100644 --- a/packages/page-parachains/src/useFunds.ts +++ b/packages/page-parachains/src/useFunds.ts @@ -9,7 +9,7 @@ import type { Campaign, Campaigns } from './types'; import BN from 'bn.js'; import { useEffect, useState } from 'react'; -import { useApi, useBestNumber, useCall, useEventTrigger, useMapKeys } from '@polkadot/react-hooks'; +import { useApi, useBestNumber, useCall, useEventTrigger, useIsMountedRef, useMapKeys } from '@polkadot/react-hooks'; import { BN_ZERO, u8aConcat, u8aToHex } from '@polkadot/util'; import { blake2AsU8a, encodeAddress } from '@polkadot/util-crypto'; @@ -166,6 +166,7 @@ function extractFundIds (keys: StorageKey<[ParaId]>[]): ParaId[] { export default function useFunds (): Campaigns { const { api } = useApi(); const bestNumber = useBestNumber(); + const mountedRef = useIsMountedRef(); const trigger = useEventTrigger([api.events.crowdloan?.Created]); const paraIds = useMapKeys(api.query.crowdloan?.funds, { at: trigger.blockHash, transform: extractFundIds }); const campaigns = useCall(api.query.crowdloan?.funds.multi, [paraIds], optFundMulti); @@ -174,10 +175,10 @@ export default function useFunds (): Campaigns { // here we manually add the actual ending status and calculate the totals useEffect((): void => { - bestNumber && campaigns && leases && setResult((prev) => + mountedRef.current && bestNumber && campaigns && leases && setResult((prev) => createResult(bestNumber, api.consts.crowdloan.minContribution as BlockNumber, campaigns, leases, prev) ); - }, [api, bestNumber, campaigns, leases]); + }, [api, bestNumber, campaigns, leases, mountedRef]); return result; } diff --git a/packages/page-parachains/src/useWinningData.ts b/packages/page-parachains/src/useWinningData.ts index b88da54952..f491d1ad94 100644 --- a/packages/page-parachains/src/useWinningData.ts +++ b/packages/page-parachains/src/useWinningData.ts @@ -8,7 +8,7 @@ import type { AuctionInfo, WinnerData, Winning } from './types'; import BN from 'bn.js'; import { useEffect, useRef, useState } from 'react'; -import { useApi, useBestNumber, useCall, useEventTrigger } from '@polkadot/react-hooks'; +import { useApi, useBestNumber, useCall, useEventTrigger, useIsMountedRef } from '@polkadot/react-hooks'; import { BN_ONE, BN_ZERO, u8aEq } from '@polkadot/util'; import { CROWD_PREFIX } from './constants'; @@ -123,6 +123,7 @@ function mergeFirst (ranges: [number, number][], auctionInfo: AuctionInfo, prev: export default function useWinningData (auctionInfo?: AuctionInfo): Winning[] | undefined { const { api } = useApi(); + const mountedRef = useIsMountedRef(); const ranges = useLeaseRanges(); const [result, setResult] = useState(); const bestNumber = useBestNumber(); @@ -133,17 +134,17 @@ export default function useWinningData (auctionInfo?: AuctionInfo): Winning[] | // should be fired once, all entries as an initial round useEffect((): void => { - auctionInfo && initialEntries && setResult( + mountedRef.current && auctionInfo && initialEntries && setResult( extractData(ranges, auctionInfo, initialEntries) ); - }, [auctionInfo, initialEntries, ranges]); + }, [auctionInfo, initialEntries, mountedRef, ranges]); // when block 0 changes, update (typically in non-ending-period, static otherwise) useEffect((): void => { - auctionInfo && optFirstData && setResult((prev) => + mountedRef.current && auctionInfo && optFirstData && setResult((prev) => mergeFirst(ranges, auctionInfo, prev, optFirstData) ); - }, [auctionInfo, optFirstData, ranges]); + }, [auctionInfo, optFirstData, mountedRef, ranges]); // on a bid event, get the new entry (assuming the event really triggered, i.e. not just a block) // and add it to the list when not duplicated. Additionally we cleanup after ourselves when endBlock @@ -156,12 +157,14 @@ export default function useWinningData (auctionInfo?: AuctionInfo): Winning[] | api.query.auctions ?.winning>(blockOffset) - .then((optCurrent) => setResult((prev) => - mergeCurrent(ranges, auctionInfo, prev, optCurrent, blockOffset) - )) + .then((optCurrent) => + mountedRef.current && setResult((prev) => + mergeCurrent(ranges, auctionInfo, prev, optCurrent, blockOffset) + ) + ) .catch(console.error); } - }, [api, bestNumber, auctionInfo, ranges, trigger, triggerRef]); + }, [api, bestNumber, auctionInfo, mountedRef, ranges, trigger, triggerRef]); return result; }