diff --git a/packages/page-accounts/src/Vanity/index.tsx b/packages/page-accounts/src/Vanity/index.tsx index c7f6b1ac7d..31f029b769 100644 --- a/packages/page-accounts/src/Vanity/index.tsx +++ b/packages/page-accounts/src/Vanity/index.tsx @@ -11,6 +11,7 @@ import styled from 'styled-components'; import { Button, Dropdown, Input, Table } from '@polkadot/react-components'; import { useApi, useIsMountedRef } from '@polkadot/react-hooks'; import { settings } from '@polkadot/ui-settings'; +import { nextTick } from '@polkadot/util'; import generator from '@polkadot/vanitygen/generator'; import matchRegex from '@polkadot/vanitygen/regex'; import generatorSort from '@polkadot/vanitygen/sort'; @@ -109,7 +110,7 @@ function VanityApp ({ className = '', onStatusChange }: Props): React.ReactEleme return _checkMatches(); } - setTimeout((): void => { + nextTick((): void => { if (mountedRef.current) { if (results.current.length === 25) { _checkMatches(); @@ -121,7 +122,7 @@ function VanityApp ({ className = '', onStatusChange }: Props): React.ReactEleme _executeGeneration(); } - }, 0); + }); }, [_checkMatches, api, match, mountedRef, runningRef, type, withCase] ); diff --git a/packages/page-accounts/src/modals/Backup.tsx b/packages/page-accounts/src/modals/Backup.tsx index 59c96c355f..9cd508c1c4 100644 --- a/packages/page-accounts/src/modals/Backup.tsx +++ b/packages/page-accounts/src/modals/Backup.tsx @@ -6,6 +6,7 @@ import React, { useCallback, useState } from 'react'; import { AddressRow, Button, Modal, Password } from '@polkadot/react-components'; import { keyring } from '@polkadot/ui-keyring'; +import { nextTick } from '@polkadot/util'; import { useTranslation } from '../translate'; @@ -32,7 +33,7 @@ function Backup ({ address, onClose }: Props): React.ReactElement { const _doBackup = useCallback( (): void => { setIsBusy(true); - setTimeout((): void => { + nextTick((): void => { try { const addressKeyring = address && keyring.getPair(address); const json = addressKeyring && keyring.backupAccount(addressKeyring, password); @@ -49,7 +50,7 @@ function Backup ({ address, onClose }: Props): React.ReactElement { setIsBusy(false); onClose(); - }, 0); + }); }, [address, onClose, password] ); diff --git a/packages/page-accounts/src/modals/ChangePass.tsx b/packages/page-accounts/src/modals/ChangePass.tsx index 7b930bd1dc..ae4d03a837 100644 --- a/packages/page-accounts/src/modals/ChangePass.tsx +++ b/packages/page-accounts/src/modals/ChangePass.tsx @@ -5,6 +5,7 @@ import React, { useCallback, useState } from 'react'; import { AddressRow, Button, Modal, Password, PasswordStrength } from '@polkadot/react-components'; import { keyring } from '@polkadot/ui-keyring'; +import { nextTick } from '@polkadot/util'; import { useTranslation } from '../translate'; @@ -57,7 +58,7 @@ function ChangePass ({ address, className = '', onClose }: Props): React.ReactEl } setIsBusy(true); - setTimeout((): void => { + nextTick((): void => { try { if (!account.isLocked) { account.lock(); @@ -82,7 +83,7 @@ function ChangePass ({ address, className = '', onClose }: Props): React.ReactEl setIsBusy(false); onClose(); - }, 0); + }); }, [address, newPass1, oldPass, onClose] ); diff --git a/packages/page-accounts/src/modals/Create.tsx b/packages/page-accounts/src/modals/Create.tsx index fbc638daef..93c188cde8 100644 --- a/packages/page-accounts/src/modals/Create.tsx +++ b/packages/page-accounts/src/modals/Create.tsx @@ -12,7 +12,7 @@ import { AddressRow, Button, Checkbox, CopyButton, Dropdown, Expander, Input, Ma import { useApi, useLedger, useStepper } from '@polkadot/react-hooks'; import { keyring } from '@polkadot/ui-keyring'; import { settings } from '@polkadot/ui-settings'; -import { isHex, u8aToHex } from '@polkadot/util'; +import { isHex, nextTick, u8aToHex } from '@polkadot/util'; import { hdLedger, hdValidatePath, keyExtractSuri, mnemonicGenerate, mnemonicValidate, randomAsU8a } from '@polkadot/util-crypto'; import { useTranslation } from '../translate'; @@ -229,14 +229,14 @@ function Create ({ className = '', onClose, onStatusChange, seed: propsSeed, typ } setIsBusy(true); - setTimeout((): void => { + nextTick((): void => { const options = { genesisHash: isDevelopment ? undefined : api.genesisHash.toString(), isHardware: false, name: name.trim() }; const status = createAccount(seed, derivePath, pairType, options, password, t('created account')); onStatusChange(status); setIsBusy(false); onClose(); - }, 0); + }); }, [api, derivePath, isDevelopment, isValid, name, onClose, onStatusChange, pairType, password, seed, t] ); diff --git a/packages/page-accounts/src/modals/Derive.tsx b/packages/page-accounts/src/modals/Derive.tsx index da4fb39169..000931c6b2 100644 --- a/packages/page-accounts/src/modals/Derive.tsx +++ b/packages/page-accounts/src/modals/Derive.tsx @@ -10,6 +10,7 @@ import React, { useCallback, useContext, useEffect, useState } from 'react'; import { AddressRow, Button, Input, InputAddress, MarkError, Modal, Password, StatusContext } from '@polkadot/react-components'; import { useApi, useDebounce, useToggle } from '@polkadot/react-hooks'; import { keyring } from '@polkadot/ui-keyring'; +import { nextTick } from '@polkadot/util'; import { keyExtractPath } from '@polkadot/util-crypto'; import { useTranslation } from '../translate'; @@ -112,7 +113,7 @@ function Derive ({ className = '', from, onClose }: Props): React.ReactElement { const _onUnlock = useCallback( (): void => { setIsBusy(true); - setTimeout((): void => { + nextTick((): void => { try { source.decodePkcs8(rootPass); setIsLocked({ isLocked: source.isLocked, lockedError: null }); @@ -122,7 +123,7 @@ function Derive ({ className = '', from, onClose }: Props): React.ReactElement { } setIsBusy(false); - }, 0); + }); }, [rootPass, source] ); @@ -134,13 +135,13 @@ function Derive ({ className = '', from, onClose }: Props): React.ReactElement { } setIsBusy(true); - setTimeout((): void => { + nextTick((): void => { const status = createAccount(source, suri, name, password, t('created account'), isDevelopment ? undefined : api.genesisHash.toString()); queueAction(status); setIsBusy(false); onClose(); - }, 0); + }); }, [api, isDevelopment, isValid, name, onClose, password, queueAction, source, suri, t] ); diff --git a/packages/page-accounts/src/modals/Import.tsx b/packages/page-accounts/src/modals/Import.tsx index a622c68df1..d17ebd34df 100644 --- a/packages/page-accounts/src/modals/Import.tsx +++ b/packages/page-accounts/src/modals/Import.tsx @@ -11,7 +11,7 @@ import React, { useCallback, useMemo, useState } from 'react'; import { AddressRow, Button, InputAddress, InputFile, MarkError, MarkWarning, Modal, Password } from '@polkadot/react-components'; import { useApi } from '@polkadot/react-hooks'; import { keyring } from '@polkadot/ui-keyring'; -import { assert, u8aToString } from '@polkadot/util'; +import { assert, nextTick, u8aToString } from '@polkadot/util'; import { useTranslation } from '../translate'; import ExternalWarning from './ExternalWarning'; @@ -75,7 +75,7 @@ function Import ({ className = '', onClose, onStatusChange }: Props): React.Reac } setIsBusy(true); - setTimeout((): void => { + nextTick((): void => { const status: Partial = { action: 'restore' }; try { @@ -100,7 +100,7 @@ function Import ({ className = '', onClose, onStatusChange }: Props): React.Reac if (status.status !== 'error') { onClose(); } - }, 0); + }); }, [onClose, onStatusChange, pair, password, t] ); diff --git a/packages/page-contracts/src/useContracts.ts b/packages/page-contracts/src/useContracts.ts index 56e4a63981..cca90914ee 100644 --- a/packages/page-contracts/src/useContracts.ts +++ b/packages/page-contracts/src/useContracts.ts @@ -5,6 +5,7 @@ import { useEffect, useState } from 'react'; import { createNamedHook, useIsMountedRef } from '@polkadot/react-hooks'; import { keyring } from '@polkadot/ui-keyring'; +import { nextTick } from '@polkadot/util'; interface UseContracts { allContracts: string[]; @@ -34,7 +35,7 @@ function useContractsImpl (): UseContracts { }); return (): void => { - setTimeout(() => subscription.unsubscribe(), 0); + nextTick(() => subscription.unsubscribe()); }; // eslint-disable-next-line react-hooks/exhaustive-deps }, []); diff --git a/packages/page-files/src/UploadModal.tsx b/packages/page-files/src/UploadModal.tsx index 24bc66abcb..a3ccdfd04f 100644 --- a/packages/page-files/src/UploadModal.tsx +++ b/packages/page-files/src/UploadModal.tsx @@ -11,7 +11,7 @@ import { createAuthIpfsEndpoints } from '@polkadot/apps-config'; import { web3FromSource } from '@polkadot/extension-dapp'; import { Available, Button, Dropdown, InputAddress, Label, MarkError, Modal, Password } from '@polkadot/react-components'; import { keyring } from '@polkadot/ui-keyring'; -import { isFunction, stringToHex, stringToU8a, u8aToHex } from '@polkadot/util'; +import { isFunction, nextTick, stringToHex, stringToU8a, u8aToHex } from '@polkadot/util'; import Progress from './Progress'; import { useTranslation } from './translate'; @@ -133,14 +133,14 @@ function UploadModal ({ className, file, onClose = NOOP, onSuccess = NOOP }: Pro const unLock = useCallback(() => { return new Promise((resolve, reject) => { - setTimeout(() => { + nextTick((): void => { try { currentPair.decodePkcs8(password); resolve(1); } catch (error) { reject(error); } - }, 0); + }); }); }, [currentPair, password]); diff --git a/packages/page-signing/src/Unlock.tsx b/packages/page-signing/src/Unlock.tsx index 9bf2dc475a..91892106df 100644 --- a/packages/page-signing/src/Unlock.tsx +++ b/packages/page-signing/src/Unlock.tsx @@ -6,6 +6,7 @@ import type { KeyringPair } from '@polkadot/keyring/types'; import React, { useCallback, useEffect, useState } from 'react'; import { Button, InputAddress, Modal, Password } from '@polkadot/react-components'; +import { nextTick } from '@polkadot/util'; import { useTranslation } from './translate'; @@ -37,7 +38,7 @@ function Unlock ({ onClose, onUnlock, pair }: Props): React.ReactElement } setIsBusy(true); - setTimeout((): void => { + nextTick((): void => { try { pair.decodePkcs8(password); } catch (error) { @@ -48,7 +49,7 @@ function Unlock ({ onClose, onUnlock, pair }: Props): React.ReactElement setIsBusy(false); onUnlock(); - }, 0); + }); }, [onUnlock, pair, password] ); diff --git a/packages/react-api/src/hoc/call.tsx b/packages/react-api/src/hoc/call.tsx index 5f77b3d218..26bfe7b977 100644 --- a/packages/react-api/src/hoc/call.tsx +++ b/packages/react-api/src/hoc/call.tsx @@ -14,7 +14,7 @@ import type { Options } from './types'; import React from 'react'; -import { assert, isNull, isUndefined } from '@polkadot/util'; +import { assert, isNull, isUndefined, nextTick } from '@polkadot/util'; import echoTransform from '../transform/echo'; import { isEqual, triggerChange } from '../util'; @@ -92,12 +92,12 @@ export default function withCall

(endpoint: string, { at, at // The attachment takes time when a lot is available, set a timeout // to first handle the current queue before subscribing - setTimeout((): void => { + nextTick((): void => { this .subscribe(this.getParams(this.props)) .then(NOOP) .catch(NOOP); - }, 0); + }); } public override componentWillUnmount (): void { diff --git a/packages/react-hooks/src/useAccounts.ts b/packages/react-hooks/src/useAccounts.ts index 9a29acb6ff..6bf0f8e5a2 100644 --- a/packages/react-hooks/src/useAccounts.ts +++ b/packages/react-hooks/src/useAccounts.ts @@ -6,7 +6,7 @@ import type { SubjectInfo } from '@polkadot/ui-keyring/observable/types'; import { useEffect, useState } from 'react'; import { keyring } from '@polkadot/ui-keyring'; -import { u8aToHex } from '@polkadot/util'; +import { nextTick, u8aToHex } from '@polkadot/util'; import { decodeAddress } from '@polkadot/util-crypto'; import { createNamedHook } from './createNamedHook'; @@ -41,7 +41,7 @@ function useAccountsImpl (): UseAccounts { ); return (): void => { - setTimeout(() => subscription.unsubscribe(), 0); + nextTick(() => subscription.unsubscribe()); }; }, [mountedRef]); diff --git a/packages/react-hooks/src/useAddresses.ts b/packages/react-hooks/src/useAddresses.ts index 51cf48a1f7..fc54a7835e 100644 --- a/packages/react-hooks/src/useAddresses.ts +++ b/packages/react-hooks/src/useAddresses.ts @@ -4,6 +4,7 @@ import { useEffect, useState } from 'react'; import { keyring } from '@polkadot/ui-keyring'; +import { nextTick } from '@polkadot/util'; import { createNamedHook } from './createNamedHook'; import { useIsMountedRef } from './useIsMountedRef'; @@ -30,7 +31,7 @@ function useAddressesImpl (): UseAddresses { }); return (): void => { - setTimeout(() => subscription.unsubscribe(), 0); + nextTick(() => subscription.unsubscribe()); }; }, [mountedRef]); diff --git a/packages/react-signer/src/TxSigned.tsx b/packages/react-signer/src/TxSigned.tsx index 1fbbe24644..bc1df7d38a 100644 --- a/packages/react-signer/src/TxSigned.tsx +++ b/packages/react-signer/src/TxSigned.tsx @@ -19,7 +19,7 @@ import { web3FromSource } from '@polkadot/extension-dapp'; import { Button, ErrorBoundary, Modal, Output, StatusContext, Toggle } from '@polkadot/react-components'; import { useApi, useLedger, useToggle } from '@polkadot/react-hooks'; import { keyring } from '@polkadot/ui-keyring'; -import { assert, BN_ZERO } from '@polkadot/util'; +import { assert, BN_ZERO, nextTick } from '@polkadot/util'; import { addressEq } from '@polkadot/util-crypto'; import Address from './Address'; @@ -308,7 +308,7 @@ function TxSigned ({ className, currentItem, requestAddress }: Props): React.Rea (): void => { setBusy(true); - setTimeout((): void => { + nextTick((): void => { const errorHandler = (error: Error): void => { console.error(error); @@ -331,7 +331,7 @@ function TxSigned ({ className, currentItem, requestAddress }: Props): React.Rea .catch((error): void => { errorHandler(error as Error); }); - }, 0); + }); }, [_onSend, _onSendPayload, _onSign, _unlock, currentItem, isSubmit, queueSetTxStatus, senderInfo] ); diff --git a/packages/test-support/src/utils/waitFor.ts b/packages/test-support/src/utils/waitFor.ts index 37c04d6309..a82c3a37be 100644 --- a/packages/test-support/src/utils/waitFor.ts +++ b/packages/test-support/src/utils/waitFor.ts @@ -3,9 +3,6 @@ export type WaitOptions = { interval?: number, timeout?: number }; -export async function waitFor (predicate: () => boolean, { interval, timeout }: WaitOptions): Promise; -export async function waitFor (predicate: () => Promise, { interval, timeout }: WaitOptions): Promise; - export async function waitFor (predicate: () => Promise | boolean, { interval = 500, timeout = 10000 } = {}): Promise { const asyncPredicate = () => Promise.resolve(predicate()); @@ -23,5 +20,6 @@ export async function waitFor (predicate: () => Promise | boolean, { in return true; } -export const sleep = (ms: number): Promise => - new Promise((resolve) => setTimeout(resolve, ms)); +export function sleep (ms: number): Promise { + return new Promise((resolve) => setTimeout(resolve, ms)); +}