diff --git a/package.json b/package.json index fdffdb2c36..dae4e2a415 100644 --- a/package.json +++ b/package.json @@ -8,10 +8,10 @@ "packages/*" ], "resolutions": { - "@polkadot/api": "^1.9.0-beta.11", - "@polkadot/api-contract": "^1.9.0-beta.11", + "@polkadot/api": "^1.9.0-beta.12", + "@polkadot/api-contract": "^1.9.0-beta.12", "@polkadot/keyring": "^2.7.0-beta.8", - "@polkadot/types": "^1.9.0-beta.11", + "@polkadot/types": "^1.9.0-beta.12", "@polkadot/util": "^2.7.0-beta.8", "@polkadot/util-crypto": "^2.7.0-beta.8", "babel-core": "^7.0.0-bridge.0", @@ -36,7 +36,7 @@ "@babel/core": "^7.9.0", "@babel/register": "^7.9.0", "@babel/runtime": "^7.9.2", - "@polkadot/dev": "^0.51.8", + "@polkadot/dev": "^0.51.9", "@polkadot/ts": "^0.3.14", "@types/bn.js": "^4.11.6", "@types/chart.js": "^2.9.16", diff --git a/packages/apps/package.json b/packages/apps/package.json index 0bc08e1392..e202471e5c 100644 --- a/packages/apps/package.json +++ b/packages/apps/package.json @@ -15,7 +15,7 @@ "dependencies": { "@babel/polyfill": "^7.8.7", "@babel/runtime": "^7.9.2", - "@polkadot/dev": "^0.51.8", + "@polkadot/dev": "^0.51.9", "@polkadot/react-components": "0.40.0-beta.191", "@polkadot/react-signer": "0.40.0-beta.191", "query-string": "^6.11.1" diff --git a/packages/apps/src/Apps.tsx b/packages/apps/src/Apps.tsx index 4ca2d4a6bd..6f975b69c6 100644 --- a/packages/apps/src/Apps.tsx +++ b/packages/apps/src/Apps.tsx @@ -29,6 +29,10 @@ interface SidebarState { export const PORTAL_ID = 'portals'; +function saveSidebar (sidebar: SidebarState): SidebarState { + return store.set('sidebar', sidebar); +} + function Apps ({ className }: Props): React.ReactElement { const { systemChain, systemName } = useApi(); const [sidebar, setSidebar] = useState({ @@ -38,24 +42,17 @@ function Apps ({ className }: Props): React.ReactElement { ...store.get('sidebar', {}), isMenu: window.innerWidth < SIDEBAR_MENU_THRESHOLD }); - const uiHighlight = useMemo((): string | undefined => - getSystemChainColor(systemChain, systemName), [systemChain, systemName] + const uiHighlight = useMemo( + (): string | undefined => getSystemChainColor(systemChain, systemName), + [systemChain, systemName] ); - const { isCollapsed, isMenu, isMenuOpen } = sidebar; - const _setSidebar = useCallback( - (update: Partial): void => - setSidebar((sidebar: SidebarState) => - store.set('sidebar', { ...sidebar, ...update }) - ), + const _collapse = useCallback( + (): void => setSidebar((sidebar: SidebarState) => saveSidebar({ ...sidebar, isCollapsed: !sidebar.isCollapsed })), [] ); - const _collapse = useCallback( - (): void => _setSidebar({ isCollapsed: !isCollapsed }), - [isCollapsed] - ); const _toggleMenu = useCallback( - (): void => _setSidebar({ isCollapsed: false, isMenuOpen: true }), + (): void => setSidebar((sidebar: SidebarState) => saveSidebar({ ...sidebar, isCollapsed: false, isMenuOpen: true })), [] ); const _handleResize = useCallback( @@ -64,15 +61,18 @@ function Apps ({ className }: Props): React.ReactElement { ? SideBarTransition.MINIMISED_AND_EXPANDED : SideBarTransition.EXPANDED_AND_MAXIMISED; - _setSidebar({ + setSidebar((sidebar: SidebarState) => saveSidebar({ + ...sidebar, isMenu: transition === SideBarTransition.MINIMISED_AND_EXPANDED, isMenuOpen: false, transition - }); + })); }, [] ); + const { isCollapsed, isMenu, isMenuOpen } = sidebar; + return ( <> diff --git a/packages/apps/src/Content/Status.tsx b/packages/apps/src/Content/Status.tsx index 49e3fc8fbc..80a0407609 100644 --- a/packages/apps/src/Content/Status.tsx +++ b/packages/apps/src/Content/Status.tsx @@ -74,7 +74,7 @@ function Status ({ optionsAll, queueAction, stqueue, txqueue }: Props): React.Re const filtered = filterEvents(allAccounts, t, optionsAll, events); filtered && queueAction(filtered); - }, [allAccounts, events, optionsAll]); + }, [allAccounts, events, optionsAll, queueAction, t]); return ( | null { - const { Modal, useCounter = DUMMY_COUNTER, display, i18n, icon, name } = route; const { t } = useTranslation(); const { allAccounts, hasAccounts } = useAccounts(); const apiProps = useApi(); const sudoKey = useCall(apiProps.isApiReady && apiProps.api.query.sudo?.key, []); const [hasSudo, setHasSudo] = useState(false); const [isVisible, setIsVisible] = useState(false); - const count = useCounter(); + const count = (route.useCounter || DUMMY_COUNTER)(); useEffect((): void => { setHasSudo(!!sudoKey && allAccounts.some((address): boolean => sudoKey.eq(address))); }, [allAccounts, sudoKey]); useEffect((): void => { - const isVisible = checkVisible(name, apiProps, hasAccounts, hasSudo, display); + const isVisible = checkVisible(route.name, apiProps, hasAccounts, hasSudo, route.display); route.isIgnored = !isVisible; setIsVisible(isVisible); - }, [apiProps, hasAccounts, hasSudo]); + }, [apiProps, hasAccounts, hasSudo, route]); if (!isVisible) { return null; } + const { Modal, i18n, icon, name } = route; + const body = ( <> diff --git a/packages/apps/src/WarmUp.tsx b/packages/apps/src/WarmUp.tsx index 745e15a581..7c629d21fc 100644 --- a/packages/apps/src/WarmUp.tsx +++ b/packages/apps/src/WarmUp.tsx @@ -16,6 +16,7 @@ function WarmUp (): React.ReactElement { useEffect((): void => { setHasValues(!!fees || !!indexes || !!issuance || !!registrars || !!staking); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return ( diff --git a/packages/page-123code/src/AccountSelector.tsx b/packages/page-123code/src/AccountSelector.tsx index 81209d303f..de34e60905 100644 --- a/packages/page-123code/src/AccountSelector.tsx +++ b/packages/page-123code/src/AccountSelector.tsx @@ -15,7 +15,10 @@ interface Props { function AccountSelector ({ className, onChange }: Props): React.ReactElement { const [accountId, setAccountId] = useState(null); - useEffect((): void => onChange(accountId), [accountId]); + useEffect( + (): void => onChange(accountId), + [accountId, onChange] + ); return (
diff --git a/packages/page-accounts/src/Accounts/Account.tsx b/packages/page-accounts/src/Accounts/Account.tsx index 475edb0143..5c609c4d4a 100644 --- a/packages/page-accounts/src/Accounts/Account.tsx +++ b/packages/page-accounts/src/Accounts/Account.tsx @@ -71,7 +71,7 @@ function Account ({ address, className, filter, isFavorite, toggleFavorite }: Pr } else if (nickname) { setAccName(nickname); } - }, [info]); + }, [api, info]); useEffect((): void => { const account = keyring.getAccount(address); @@ -84,7 +84,7 @@ function Account ({ address, className, filter, isFavorite, toggleFavorite }: Pr }); _setTags(account?.meta.tags || []); setAccName(account?.meta.name || ''); - }, [address]); + }, [address, _setTags]); useEffect((): void => { if (filter.length === 0) { diff --git a/packages/page-accounts/src/Accounts/modals/Derive.tsx b/packages/page-accounts/src/Accounts/modals/Derive.tsx index 35514d6b21..e6ed0dece1 100644 --- a/packages/page-accounts/src/Accounts/modals/Derive.tsx +++ b/packages/page-accounts/src/Accounts/modals/Derive.tsx @@ -92,14 +92,14 @@ function Derive ({ className, from, onClose }: Props): React.ReactElement { const deriveError = deriveValidate(debouncedSuri, source.type); if (!deriveError) { - const result = source.derive(suri); + const result = source.derive(debouncedSuri); address = result.address; } return { address, deriveError }; }); - }, [debouncedSuri]); + }, [debouncedSuri, source]); const _onChangeName = (name: string): void => setName({ isNameValid: !!name.trim(), name }); diff --git a/packages/page-accounts/src/Accounts/modals/Transfer.tsx b/packages/page-accounts/src/Accounts/modals/Transfer.tsx index 137f62b312..385971124e 100644 --- a/packages/page-accounts/src/Accounts/modals/Transfer.tsx +++ b/packages/page-accounts/src/Accounts/modals/Transfer.tsx @@ -36,7 +36,7 @@ function Transfer ({ className, onClose, recipientId: propRecipientId, senderId: senderId && recipientId && setExtrinsic( () => api.tx.balances.transfer(recipientId, amount || ZERO) ); - }, [amount, recipientId, senderId]); + }, [api, amount, recipientId, senderId]); const transferrable = {t('transferrable')}; diff --git a/packages/page-accounts/src/Contacts/Address.tsx b/packages/page-accounts/src/Contacts/Address.tsx index 1b8dc11d04..f338b27c5a 100644 --- a/packages/page-accounts/src/Contacts/Address.tsx +++ b/packages/page-accounts/src/Contacts/Address.tsx @@ -45,6 +45,14 @@ function Address ({ address, className, filter, isFavorite, toggleFavorite }: Pr const _setTags = (tags: string[]): void => setTags(tags.sort()); + useEffect((): void => { + const current = keyring.getAddress(address); + + setCurrent(current || null); + setGenesisHash((current && current.meta.genesisHash) || null); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + useEffect((): void => { const { identity, nickname } = info || {}; @@ -55,14 +63,7 @@ function Address ({ address, className, filter, isFavorite, toggleFavorite }: Pr } else if (nickname) { setAccName(nickname); } - }, [info]); - - useEffect((): void => { - const current = keyring.getAddress(address); - - setCurrent(current || null); - setGenesisHash((current && current.meta.genesisHash) || null); - }, []); + }, [api, info]); useEffect((): void => { const account = keyring.getAddress(address); diff --git a/packages/page-accounts/src/Vanity/Match.tsx b/packages/page-accounts/src/Vanity/Match.tsx index 9a16edddea..e35ed9efe4 100644 --- a/packages/page-accounts/src/Vanity/Match.tsx +++ b/packages/page-accounts/src/Vanity/Match.tsx @@ -25,11 +25,11 @@ function Match ({ address, className, count, offset, onCreateToggle, onRemove, s ); const _onCreate = useCallback( (): void => onCreateToggle(hexSeed), - [hexSeed] + [hexSeed, onCreateToggle] ); const _onRemove = useCallback( (): void => onRemove(address), - [address] + [address, onRemove] ); return ( diff --git a/packages/page-claims/src/Claim.tsx b/packages/page-claims/src/Claim.tsx index 5a97f67bbe..a7cb2cd495 100644 --- a/packages/page-claims/src/Claim.tsx +++ b/packages/page-claims/src/Claim.tsx @@ -5,7 +5,7 @@ import { Option } from '@polkadot/types'; import { BalanceOf, EthereumAddress } from '@polkadot/types/interfaces'; -import React, { useEffect, useState } from 'react'; +import React, { useCallback, useEffect, useState } from 'react'; import styled from 'styled-components'; import { Button, Card } from '@polkadot/react-components'; import { useApi } from '@polkadot/react-hooks'; @@ -27,24 +27,26 @@ function Claim ({ button, className, ethereumAddress }: Props): React.ReactEleme const [claimAddress, setClaimAddress] = useState(null); const [isBusy, setIsBusy] = useState(false); - const _fetchClaim = (address: EthereumAddress): void => { - setIsBusy(true); + const _fetchClaim = useCallback( + (address: EthereumAddress): void => { + setIsBusy(true); - api.query.claims - .claims>(address) - .then((claim): void => { - setClaimValue(claim.unwrapOr(null)); - setIsBusy(false); - }) - .catch((): void => setIsBusy(false)); - }; + api.query.claims + .claims>(address) + .then((claim): void => { + setClaimValue(claim.unwrapOr(null)); + setIsBusy(false); + }) + .catch((): void => setIsBusy(false)); + }, + [api] + ); useEffect((): void => { - if (ethereumAddress !== claimAddress) { - setClaimAddress(ethereumAddress); - ethereumAddress && _fetchClaim(ethereumAddress); - } - }, [ethereumAddress]); + setClaimAddress(ethereumAddress); + + ethereumAddress && _fetchClaim(ethereumAddress); + }, [_fetchClaim, ethereumAddress]); if (isBusy || !claimAddress) { return null; diff --git a/packages/page-contracts/package.json b/packages/page-contracts/package.json index 86f6deed6f..4fab832583 100644 --- a/packages/page-contracts/package.json +++ b/packages/page-contracts/package.json @@ -12,6 +12,6 @@ "license": "Apache-2.0", "dependencies": { "@babel/runtime": "^7.9.2", - "@polkadot/api-contract": "^1.9.0-beta.11" + "@polkadot/api-contract": "^1.9.0-beta.12" } } diff --git a/packages/page-contracts/src/Contracts/Call.tsx b/packages/page-contracts/src/Contracts/Call.tsx index d493eb129d..f39b905e72 100644 --- a/packages/page-contracts/src/Contracts/Call.tsx +++ b/packages/page-contracts/src/Contracts/Call.tsx @@ -33,13 +33,8 @@ interface Props extends BareProps { function Call (props: Props): React.ReactElement | null { const { t } = useTranslation(); const { className, isOpen, callContract, callMessageIndex, onChangeCallContractAddress, onChangeCallMessageIndex, onClose } = props; - - if (isNull(callContract) || isNull(callMessageIndex)) { - return null; - } - - const hasRpc = callContract.hasRpcContractsCall; - let callMessage = callContract.getMessage(callMessageIndex); + const hasRpc = callContract?.hasRpcContractsCall; + const callMessage = callContract?.getMessage(isNull(callMessageIndex) ? undefined : callMessageIndex); const { api } = useApi(); const [accountId, setAccountId] = useState(null); @@ -51,23 +46,29 @@ function Call (props: Props): React.ReactElement | null { const [useRpc, setUseRpc] = useState(hasRpc && callMessage && !callMessage.def.mutates); useEffect((): void => { - callMessage = callContract.getMessage(callMessageIndex); + if (callContract && callMessageIndex) { + const callMessage = callContract.getMessage(callMessageIndex); - setParams(callMessage ? callMessage.def.args.map(({ type }): any => createValue({ type })) : []); + setParams(callMessage ? callMessage.def.args.map(({ type }): any => createValue({ type })) : []); - if (hasRpc) { - if (!callMessage || callMessage.def.mutates) { - setUseRpc(false); - } else { - setUseRpc(true); + if (hasRpc) { + if (!callMessage || callMessage.def.mutates) { + setUseRpc(false); + } else { + setUseRpc(true); + } } } - }, [callContract, callMessageIndex]); + }, [callContract, callMessageIndex, hasRpc]); useEffect((): void => { setOutcomes([]); }, [callContract]); + if (isNull(callContract) || isNull(callMessageIndex) || !callMessage) { + return null; + } + const _onChangeAccountId = (accountId: StringOrNull): void => setAccountId(accountId); const _onChangeCallMessageIndexString = (callMessageIndexString: string): void => { @@ -91,7 +92,7 @@ function Call (props: Props): React.ReactElement | null { }; const _onSubmitRpc = (): void => { - if (!accountId) return; + if (!accountId || !callMessage) return; callContract .call('rpc', callMessage.def.name, endowment, gasLimit, ...params) diff --git a/packages/page-contracts/src/Contracts/Contract.tsx b/packages/page-contracts/src/Contracts/Contract.tsx index 765443344c..6caf1615f3 100644 --- a/packages/page-contracts/src/Contracts/Contract.tsx +++ b/packages/page-contracts/src/Contracts/Contract.tsx @@ -31,13 +31,12 @@ const ContractCard = styled(Card)` function Contract (props: Props): React.ReactElement | null { const { t } = useTranslation(); const { contract: { abi, address }, onCall } = props; + const [isForgetOpen, setIsForgetOpen] = useState(false); if (!address || !abi) { return null; } - const [isForgetOpen, setIsForgetOpen] = useState(false); - const _toggleForget = (): void => setIsForgetOpen(!isForgetOpen); const _onForget = (): void => { if (!address) { diff --git a/packages/page-contracts/src/Contracts/ValidateAddr.tsx b/packages/page-contracts/src/Contracts/ValidateAddr.tsx index 0a6b104fb6..89e713f4cf 100644 --- a/packages/page-contracts/src/Contracts/ValidateAddr.tsx +++ b/packages/page-contracts/src/Contracts/ValidateAddr.tsx @@ -39,7 +39,7 @@ function ValidateAddr ({ address, onChange }: Props): React.ReactElement useEffect((): void => { onChange(isAddress && isStored); - }, [isAddress, isStored]); + }, [isAddress, isStored, onChange]); if (isStored || !isAddress) { return null; diff --git a/packages/page-contracts/src/Contracts/index.tsx b/packages/page-contracts/src/Contracts/index.tsx index c9195964ed..d464f67ceb 100644 --- a/packages/page-contracts/src/Contracts/index.tsx +++ b/packages/page-contracts/src/Contracts/index.tsx @@ -35,13 +35,9 @@ function Contracts (props: Props): React.ReactElement { useEffect((): void => { setContracts(filterContracts(api, props)); - }, [accounts, api, keyringContracts]); + }, [accounts, api, keyringContracts, props]); - let callContract = contracts[callContractIndex] || null; - - useEffect((): void => { - callContract = contracts[callContractIndex]; - }, [callContractIndex]); + const callContract = contracts[callContractIndex] || null; const _toggleAdd = (): void => setIsAddOpen(!isAddOpen); const _toggleCall = (): void => setIsCallOpen(!isCallOpen); diff --git a/packages/page-contracts/src/Messages.tsx b/packages/page-contracts/src/Messages.tsx index 6bc63206be..9dd77641c6 100644 --- a/packages/page-contracts/src/Messages.tsx +++ b/packages/page-contracts/src/Messages.tsx @@ -51,8 +51,7 @@ function onSelectConstructor (props: Props, index: number): () => void { }; } -function renderItem (props: Props, message: ContractABIMessage, index: number, asConstructor = false): React.ReactNode { - const { t } = useTranslation(); +function renderItem (props: Props, message: ContractABIMessage, index: number, asConstructor: boolean, t: (key: string) => string): React.ReactNode { const { docs = [], name } = message; return ( @@ -108,24 +107,24 @@ function renderItem (props: Props, message: ContractABIMessage, index: number, a ); } -function renderConstructor (props: Props, index: number): React.ReactNode { +function renderConstructor (props: Props, index: number, t: (key: string) => string): React.ReactNode { const { contractAbi: { abi: { contract: { constructors } } } } = props; if (!constructors[index]) { return null; } - return renderItem(props, constructors[index], index, true); + return renderItem(props, constructors[index], index, true, t); } -function renderMessage (props: Props, index: number): React.ReactNode { +function renderMessage (props: Props, index: number, t: (key: string) => string): React.ReactNode { const { contractAbi: { abi: { contract: { messages } } } } = props; if (!messages[index]) { return null; } - return renderItem(props, messages[index], index); + return renderItem(props, messages[index], index, false, t); } function Messages (props: Props): React.ReactElement { @@ -134,8 +133,8 @@ function Messages (props: Props): React.ReactElement { return (
- {withConstructors && constructors.map((_, index): React.ReactNode => renderConstructor(props, index))} - {messages.map((_, index): React.ReactNode => renderMessage(props, index))} + {withConstructors && constructors.map((_, index): React.ReactNode => renderConstructor(props, index, t))} + {messages.map((_, index): React.ReactNode => renderMessage(props, index, t))} {isRemovable && ( diff --git a/packages/page-council/src/Motions/Slashing.tsx b/packages/page-council/src/Motions/Slashing.tsx index f59b472993..0fb12d6997 100644 --- a/packages/page-council/src/Motions/Slashing.tsx +++ b/packages/page-council/src/Motions/Slashing.tsx @@ -49,7 +49,7 @@ function Slashing ({ className, isMember, members }: Props): React.ReactElement< } else { setEras([]); } - }, [slashes]); + }, [slashes, t]); useEffect((): void => { const actioned = selectedEra && slashes?.find(([era]): boolean => era.eqn(selectedEra)); @@ -59,7 +59,7 @@ function Slashing ({ className, isMember, members }: Props): React.ReactElement< ? api.tx.staking.cancelDeferredSlash(actioned[0], actioned[1].map((_, index): number => index)) : null ); - }, [selectedEra, slashes]); + }, [api, selectedEra, slashes]); return ( <> diff --git a/packages/page-council/src/Motions/useAvailableSlashes.ts b/packages/page-council/src/Motions/useAvailableSlashes.ts index 3081b3978a..d137617b45 100644 --- a/packages/page-council/src/Motions/useAvailableSlashes.ts +++ b/packages/page-council/src/Motions/useAvailableSlashes.ts @@ -48,7 +48,7 @@ export default function useAvailableSlashes (): [BN, UnappliedSlash[]][] { return (): void => { unsub && unsub(); }; - }, [earliestSlash, indexes]); + }, [api, earliestSlash, indexes, mountedRef]); return slashes; } diff --git a/packages/page-council/src/Overview/index.tsx b/packages/page-council/src/Overview/index.tsx index 29e2718bec..16c1bfae07 100644 --- a/packages/page-council/src/Overview/index.tsx +++ b/packages/page-council/src/Overview/index.tsx @@ -60,9 +60,11 @@ function Overview ({ className, prime }: Props): React.ReactElement { const bestNumber = useCall(api.derive.chain.bestNumber, []); const electionsInfo = useCall(api.derive.elections.info, []); const allVotes = api.query.electionsPhragmen?.votesOf.creator.meta.type.asMap.linked.isTrue + // eslint-disable-next-line react-hooks/rules-of-hooks ? useCall>(api.query.electionsPhragmen?.votesOf, [], { transform: transformVotesPrev }) + // eslint-disable-next-line react-hooks/rules-of-hooks : useCall>(api.query.electionsPhragmen?.votesOf.entries as any, [], { transform: transformVotes }); diff --git a/packages/page-democracy/src/Overview/DispatchEntry.tsx b/packages/page-democracy/src/Overview/DispatchEntry.tsx index 611cade2f4..8a37cd5566 100644 --- a/packages/page-democracy/src/Overview/DispatchEntry.tsx +++ b/packages/page-democracy/src/Overview/DispatchEntry.tsx @@ -33,7 +33,7 @@ function DispatchEntry ({ blockNumber, hash, referendumIndex }: Props): React.Re useEffect((): void => { preimage?.isSome && setProposal(api.createType('Proposal', preimage.unwrap()[0].toU8a(true))); - }, [preimage]); + }, [api, preimage]); return ( diff --git a/packages/page-democracy/src/Overview/Externals.tsx b/packages/page-democracy/src/Overview/Externals.tsx index a2c9abc8e2..203497c7c7 100644 --- a/packages/page-democracy/src/Overview/Externals.tsx +++ b/packages/page-democracy/src/Overview/Externals.tsx @@ -49,7 +49,7 @@ function Externals ({ className }: Props): React.ReactElement | null { } else { setExpanded(null); } - }, [preimage]); + }, [api, preimage]); if (!hash) { return null; diff --git a/packages/page-democracy/src/Overview/Fasttrack.tsx b/packages/page-democracy/src/Overview/Fasttrack.tsx index 2b64c1c20d..038e4c59f5 100644 --- a/packages/page-democracy/src/Overview/Fasttrack.tsx +++ b/packages/page-democracy/src/Overview/Fasttrack.tsx @@ -46,7 +46,7 @@ function Fasttrack ({ hash, threshold }: Props): React.ReactElement | nul ? api.tx.democracy.fastTrack(hash, votingBlocks, delayBlocks) : null ); - }, [delayBlocks, hash, votingBlocks]); + }, [api, delayBlocks, hash, votingBlocks]); return ( <> diff --git a/packages/page-democracy/src/useCounter.ts b/packages/page-democracy/src/useCounter.ts index 5d59ebb21e..6353b88e6d 100644 --- a/packages/page-democracy/src/useCounter.ts +++ b/packages/page-democracy/src/useCounter.ts @@ -17,7 +17,7 @@ export default function useCounter (): number { (proposals?.length || 0) + (referenda?.length || 0) ); - }, [proposals, referenda]); + }, [mountedRef, proposals, referenda]); return counter; } diff --git a/packages/page-explorer/src/BlockInfo/index.tsx b/packages/page-explorer/src/BlockInfo/index.tsx index d397e702db..4eebbcb5fb 100644 --- a/packages/page-explorer/src/BlockInfo/index.tsx +++ b/packages/page-explorer/src/BlockInfo/index.tsx @@ -20,11 +20,13 @@ function Entry (): React.ReactElement<{}> | null { const [stateValue, setStateValue] = useState(value); useEffect((): void => { - if (value && value !== stateValue) { - setStateValue(value); - } else if (!stateValue && bestNumber) { - setStateValue(bestNumber.toString()); - } + setStateValue((stateValue) => + value && value !== stateValue + ? value + : !stateValue && bestNumber + ? bestNumber.toString() + : stateValue + ); }, [bestNumber, value]); if (!stateValue) { diff --git a/packages/page-explorer/src/Forks.tsx b/packages/page-explorer/src/Forks.tsx index fa14443062..93801b0741 100644 --- a/packages/page-explorer/src/Forks.tsx +++ b/packages/page-explorer/src/Forks.tsx @@ -352,6 +352,7 @@ function Forks ({ className }: Props): React.ReactElement | null { _subFinHead && _subFinHead(); _subNewHead && _subNewHead(); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); if (!tree) { diff --git a/packages/page-explorer/src/NodeInfo/index.tsx b/packages/page-explorer/src/NodeInfo/index.tsx index f290e0183d..67a2c871b4 100644 --- a/packages/page-explorer/src/NodeInfo/index.tsx +++ b/packages/page-explorer/src/NodeInfo/index.tsx @@ -51,6 +51,7 @@ function NodeInfo (): React.ReactElement<{}> { return (): void => { window.clearInterval(timerId); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return ( diff --git a/packages/page-generic-asset/src/Transfer.tsx b/packages/page-generic-asset/src/Transfer.tsx index 6a8587e562..a8575c0bcc 100644 --- a/packages/page-generic-asset/src/Transfer.tsx +++ b/packages/page-generic-asset/src/Transfer.tsx @@ -55,7 +55,7 @@ function Transfer ({ assets, className, onClose, recipientId: propRecipientId, s ? api.tx.genericAsset.transfer(assetId, recipientId, amount) : null ); - }, [amount, assetId, recipientId, senderId]); + }, [api, amount, assetId, recipientId, senderId]); const _onAddAssetId = (id: string): void => { // eslint-disable-next-line @typescript-eslint/prefer-regexp-exec diff --git a/packages/page-js/src/Playground.tsx b/packages/page-js/src/Playground.tsx index c3e27a4e71..dc7fca0bc6 100644 --- a/packages/page-js/src/Playground.tsx +++ b/packages/page-js/src/Playground.tsx @@ -106,6 +106,7 @@ function Playground ({ className }: Props): React.ReactElement { setIsCustomExample((selected && selected.type === 'custom') || false); setOptions(options); setSelected(selected || snippets[0]); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); useEffect((): void => { diff --git a/packages/page-parachains/src/Overview/Register.tsx b/packages/page-parachains/src/Overview/Register.tsx index 3d7fd3d26c..5d9e462334 100644 --- a/packages/page-parachains/src/Overview/Register.tsx +++ b/packages/page-parachains/src/Overview/Register.tsx @@ -56,7 +56,7 @@ function Register ({ nextFreeId = ONE_THOUSAND, sudoKey }: Props): React.ReactEl (): ParaInfo => { return createType(api.registry, 'ParaInfo', { scheduling }); }, - [scheduling] + [api, scheduling] ); const extrinsic = useMemo( (): SubmittableExtrinsic | null => { @@ -72,7 +72,7 @@ function Register ({ nextFreeId = ONE_THOUSAND, sudoKey }: Props): React.ReactEl return null; } }, - [id, info, code, initialHeadState] + [api, id, info, code, initialHeadState] ); return ( diff --git a/packages/page-parachains/src/Parachain/Deregister.tsx b/packages/page-parachains/src/Parachain/Deregister.tsx index ea838e65e9..f19b75b7e8 100644 --- a/packages/page-parachains/src/Parachain/Deregister.tsx +++ b/packages/page-parachains/src/Parachain/Deregister.tsx @@ -37,7 +37,7 @@ function Deregister ({ id, info, isOpen, onClose, onSubmit, sudoKey }: Props): R return null; } }, - [id] + [api, id] ); const onStart = (): void => { diff --git a/packages/page-parachains/src/index.tsx b/packages/page-parachains/src/index.tsx index 9bb8fbc0af..9d67e3f353 100644 --- a/packages/page-parachains/src/index.tsx +++ b/packages/page-parachains/src/index.tsx @@ -39,7 +39,7 @@ function ParachainsApp ({ basePath }: Props): React.ReactElement { }] : [] ) - ], [location, paraInfoRef.current, t]); + ], [match, t]); return (
diff --git a/packages/page-settings/src/Metadata/Extensions.tsx b/packages/page-settings/src/Metadata/Extensions.tsx index 6c31547381..e1b3792d3e 100644 --- a/packages/page-settings/src/Metadata/Extensions.tsx +++ b/packages/page-settings/src/Metadata/Extensions.tsx @@ -31,7 +31,7 @@ function Extensions (): React.ReactElement { .then(() => toggleBusy()); } }, - [extensions, metaDef, selectedIndex] + [extensions, metaDef, selectedIndex, toggleBusy] ); if (!options.length) { diff --git a/packages/page-settings/src/SelectUrl.tsx b/packages/page-settings/src/SelectUrl.tsx index ee2b8b7334..f0aa7cad0d 100644 --- a/packages/page-settings/src/SelectUrl.tsx +++ b/packages/page-settings/src/SelectUrl.tsx @@ -71,6 +71,9 @@ function SelectUrl ({ className, onChange }: Props): React.ReactElement { useEffect((): void => { onChange && info.isValid && onChange(info.url); + // the issue here is that the onChange callback changes each and every render... so Houston, we have + // a desperate issue here :( + // eslint-disable-next-line react-hooks/exhaustive-deps }, [info]); const _onChangeUrl = useCallback( @@ -87,7 +90,7 @@ function SelectUrl ({ className, onChange }: Props): React.ReactElement { ), isCustom }), - [] + [info] ); return ( diff --git a/packages/page-staking/src/Actions/Account/InjectKeys.tsx b/packages/page-staking/src/Actions/Account/InjectKeys.tsx index 503e279751..ef2dc5bddc 100644 --- a/packages/page-staking/src/Actions/Account/InjectKeys.tsx +++ b/packages/page-staking/src/Actions/Account/InjectKeys.tsx @@ -63,7 +63,7 @@ function InjectKeys ({ onClose }: Props): React.ReactElement | null { rpc: { section: 'author', method: 'insertKey' } as any, values: [keyType, suri, publicKey] }), - [keyType, publicKey, suri] + [keyType, publicKey, queueRpc, suri] ); const _cryptoOptions = useMemo( () => CRYPTO_MAP[keyType].map((value): { text: string; value: KeypairType } => ({ diff --git a/packages/page-staking/src/Actions/Account/InputValidateAmount.tsx b/packages/page-staking/src/Actions/Account/InputValidateAmount.tsx index 3cce3732b8..9c186b8d40 100644 --- a/packages/page-staking/src/Actions/Account/InputValidateAmount.tsx +++ b/packages/page-staking/src/Actions/Account/InputValidateAmount.tsx @@ -33,12 +33,10 @@ function ValidateAmount ({ accountId, onError, value }: Props): React.ReactEleme newError = t('The specified value is greater than your free balance. The node will bond the maximum amount available.'); } - if (error !== newError) { - onError(newError); - setError(newError); - } + onError(newError); + setError((error) => error !== newError ? newError : error); } - }, [allBalances, value]); + }, [allBalances, onError, t, value]); if (!error) { return null; diff --git a/packages/page-staking/src/Actions/Account/InputValidationController.tsx b/packages/page-staking/src/Actions/Account/InputValidationController.tsx index 6b3d0caf60..34b6ae3fc3 100644 --- a/packages/page-staking/src/Actions/Account/InputValidationController.tsx +++ b/packages/page-staking/src/Actions/Account/InputValidationController.tsx @@ -49,12 +49,10 @@ function ValidateController ({ accountId, controllerId, defaultController, onErr newError = t('A controller account should not be set to manages multiple stashes. The selected controller is already controlling {{stashId}}', { replace: { stashId } }); } - if (error !== newError) { - onError(newError); - setError(newError); - } + onError(newError); + setError((error) => error !== newError ? newError : error); } - }, [accountId, bondedId, controllerId, defaultController, stashId]); + }, [accountId, bondedId, controllerId, defaultController, onError, stashId, t]); if (!error || !accountId) { return null; diff --git a/packages/page-staking/src/Actions/Account/InputValidationSessionKey.tsx b/packages/page-staking/src/Actions/Account/InputValidationSessionKey.tsx index 3ddb364a55..052635e145 100644 --- a/packages/page-staking/src/Actions/Account/InputValidationSessionKey.tsx +++ b/packages/page-staking/src/Actions/Account/InputValidationSessionKey.tsx @@ -21,17 +21,15 @@ function ValidateSessionEd25519 ({ onError, sessionId, stashId }: Props): React. const [error, setError] = useState(null); useEffect((): void => { - let newError = null; + let newError: string | null = null; if (sessionId === stashId) { newError = t('For fund security, your session key should not match your stash key.'); } - if (error !== newError) { - onError(newError); - setError(newError); - } - }, [sessionId, stashId]); + onError(newError); + setError((error) => error !== newError ? newError : error); + }, [onError, sessionId, stashId, t]); if (!error) { return null; diff --git a/packages/page-staking/src/Actions/Account/InputValidationUnstakeThreshold.tsx b/packages/page-staking/src/Actions/Account/InputValidationUnstakeThreshold.tsx index 9ac4bd4bd8..cb269544fa 100644 --- a/packages/page-staking/src/Actions/Account/InputValidationUnstakeThreshold.tsx +++ b/packages/page-staking/src/Actions/Account/InputValidationUnstakeThreshold.tsx @@ -19,7 +19,7 @@ function InputValidationUnstakeThreshold ({ onError, unstakeThreshold }: Props): useEffect((): void => { if (unstakeThreshold) { - let newError = null; + let newError: string | null = null; if (unstakeThreshold.ltn(0)) { newError = t('The Threshold must be a positive number'); @@ -27,12 +27,10 @@ function InputValidationUnstakeThreshold ({ onError, unstakeThreshold }: Props): newError = t('The Threshold must lower than 11'); } - if (newError !== error) { - onError(newError); - setError(newError); - } + onError(newError); + setError((error) => error !== newError ? newError : error); } - }, [unstakeThreshold]); + }, [onError, t, unstakeThreshold]); if (!error) { return null; diff --git a/packages/page-staking/src/Actions/Account/index.tsx b/packages/page-staking/src/Actions/Account/index.tsx index c4b1a8a2e6..0e7c814f2b 100644 --- a/packages/page-staking/src/Actions/Account/index.tsx +++ b/packages/page-staking/src/Actions/Account/index.tsx @@ -146,7 +146,7 @@ function Account ({ allStashes, className, isOwnStash, next, onUpdateType, rewar onUpdateType(stashId, 'other'); } } - }, [allStashes, stakingAccount, stashId, validateInfo]); + }, [allAccounts, allStashes, onUpdateType, stakingAccount, stashId, validateInfo]); useEffect((): void => { nominees && setActiveNoms( @@ -167,7 +167,7 @@ function Account ({ allStashes, className, isOwnStash, next, onUpdateType, rewar accountId: controllerId, extrinsic: createPayout(api, payoutRewards) }), - [api, controllerId, payoutRewards] + [api, controllerId, payoutRewards, queueExtrinsic] ); return ( diff --git a/packages/page-staking/src/Actions/Account/useInactives.ts b/packages/page-staking/src/Actions/Account/useInactives.ts index 7d3c01fb58..937e879852 100644 --- a/packages/page-staking/src/Actions/Account/useInactives.ts +++ b/packages/page-staking/src/Actions/Account/useInactives.ts @@ -43,7 +43,7 @@ export default function useInactives (stashId: string, nominees?: string[]): str return (): void => { unsub && unsub(); }; - }, [indexes, nominees, stashId]); + }, [api, indexes, mountedRef, nominees, stashId]); return inactives; } diff --git a/packages/page-staking/src/Overview/Address/Favorite.tsx b/packages/page-staking/src/Overview/Address/Favorite.tsx index 58df79817f..e781814f38 100644 --- a/packages/page-staking/src/Overview/Address/Favorite.tsx +++ b/packages/page-staking/src/Overview/Address/Favorite.tsx @@ -14,7 +14,7 @@ interface Props { function Favorite ({ address, isFavorite, toggleFavorite }: Props): React.ReactElement { const _onFavorite = useCallback( (): void => toggleFavorite(address), - [address] + [address, toggleFavorite] ); return ( diff --git a/packages/page-staking/src/Overview/Address/index.tsx b/packages/page-staking/src/Overview/Address/index.tsx index add9ab9cf6..820a7447ce 100644 --- a/packages/page-staking/src/Overview/Address/index.tsx +++ b/packages/page-staking/src/Overview/Address/index.tsx @@ -115,13 +115,13 @@ function Address ({ address, className, filterName, hasQueries, isAuthor, isElec setNominators && setNominators(info.nominators.map(([who]): string => who.toString())); setStakingState(info); } - }, [stakingInfo]); + }, [setNominators, stakingInfo, withNominations]); useEffect((): void => { setIsVisible( checkVisibility(api, address, filterName, info) ); - }, [address, filterName, info]); + }, [address, api, filterName, info]); const _onQueryStats = useCallback( (): void => { diff --git a/packages/page-staking/src/Query/ChartRewards.tsx b/packages/page-staking/src/Query/ChartRewards.tsx index 3cdf777f32..4bd0bdf30b 100644 --- a/packages/page-staking/src/Query/ChartRewards.tsx +++ b/packages/page-staking/src/Query/ChartRewards.tsx @@ -62,7 +62,7 @@ function ChartRewards ({ validatorId }: Props): React.ReactElement { const { currency, divisor } = useMemo((): { currency: string; divisor: BN } => ({ currency: formatBalance.getDefaults().unit, divisor: new BN('1'.padEnd(formatBalance.getDefaults().decimals + 1, '0')) - }), [formatBalance]); + }), []); const legends = useMemo(() => [ t('{{currency}} slashed', { replace: { currency } }), t('{{currency}} rewards', { replace: { currency } }), @@ -73,7 +73,7 @@ function ChartRewards ({ validatorId }: Props): React.ReactElement { erasRewards && ownSlashes && stakerPoints && setChart( extractRewards(erasRewards, ownSlashes, stakerPoints, divisor) ); - }, [erasRewards, stakerPoints]); + }, [divisor, erasRewards, ownSlashes, stakerPoints]); return (
diff --git a/packages/page-staking/src/Query/ChartStake.tsx b/packages/page-staking/src/Query/ChartStake.tsx index abe8f9e960..1ecf8902b0 100644 --- a/packages/page-staking/src/Query/ChartStake.tsx +++ b/packages/page-staking/src/Query/ChartStake.tsx @@ -54,7 +54,7 @@ function ChartStake ({ validatorId }: Props): React.ReactElement { const { currency, divisor } = useMemo((): { currency: string; divisor: BN } => ({ currency: formatBalance.getDefaults().unit, divisor: new BN('1'.padEnd(formatBalance.getDefaults().decimals + 1, '0')) - }), [formatBalance]); + }), []); const legends = useMemo(() => [ t('{{currency}} clipped', { replace: { currency } }), t('{{currency}} total', { replace: { currency } }), @@ -65,7 +65,7 @@ function ChartStake ({ validatorId }: Props): React.ReactElement { ownExposure && setChart( extractStake(ownExposure, divisor) ); - }, [ownExposure]); + }, [divisor, ownExposure]); return (
diff --git a/packages/page-staking/src/Query/useBlockCounts.tsx b/packages/page-staking/src/Query/useBlockCounts.tsx index 8e9b131fd5..67f1981839 100644 --- a/packages/page-staking/src/Query/useBlockCounts.tsx +++ b/packages/page-staking/src/Query/useBlockCounts.tsx @@ -31,11 +31,11 @@ export default function useBlockCounts (accountId: string, sessionRewards: Sessi }); } } - }, [accountId, sessionRewards]); + }, [accountId, api, mountedRef, sessionRewards]); useEffect((): void => { setCounts([...historic, current || api.createType('u32')].slice(1)); - }, [current, historic]); + }, [api, current, historic]); return counts; } diff --git a/packages/page-staking/src/Targets/index.tsx b/packages/page-staking/src/Targets/index.tsx index 6d46a73e34..b24655db7e 100644 --- a/packages/page-staking/src/Targets/index.tsx +++ b/packages/page-staking/src/Targets/index.tsx @@ -195,7 +195,7 @@ function Targets ({ className }: Props): React.ReactElement { ? !sortFromMax : true })), - [sortBy] + [] ); useEffect((): void => { diff --git a/packages/react-api/package.json b/packages/react-api/package.json index 523e13082a..d412477363 100644 --- a/packages/react-api/package.json +++ b/packages/react-api/package.json @@ -31,8 +31,8 @@ "homepage": "https://github.com/polkadot-js/ui/tree/master/packages/ui-reactive#readme", "dependencies": { "@babel/runtime": "^7.9.2", - "@polkadot/api": "^1.9.0-beta.11", - "@polkadot/extension-dapp": "^0.23.0-beta.10", + "@polkadot/api": "^1.9.0-beta.12", + "@polkadot/extension-dapp": "^0.23.1", "rxjs-compat": "^6.5.4" } } diff --git a/packages/react-api/src/Api.tsx b/packages/react-api/src/Api.tsx index 240d08b13d..2abe5412d4 100644 --- a/packages/react-api/src/Api.tsx +++ b/packages/react-api/src/Api.tsx @@ -172,6 +172,7 @@ function Api ({ children, url }: Props): React.ReactElement | null { .catch((error) => console.error(error)); setIsApiInitialized(true); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); if (!props.isApiInitialized) { diff --git a/packages/react-components/src/AccountName.tsx b/packages/react-components/src/AccountName.tsx index 15a4406907..d786483aa4 100644 --- a/packages/react-components/src/AccountName.tsx +++ b/packages/react-components/src/AccountName.tsx @@ -199,7 +199,7 @@ function AccountName ({ children, className, defaultName, label, onClick, overri } else { setName(defaultOrAddr(defaultName, cacheAddr, accountIndex)); } - }, [address, info, isRegistrar, toggle]); + }, [api, address, defaultName, info, isRegistrar, t, toggle, toggleJudgement]); return ( <> @@ -263,9 +263,5 @@ export default React.memo(styled(AccountName)` line-height: 1em; vertical-align: middle; } - - .ui--Badge { - margin-top: -2px; - } } `); diff --git a/packages/react-components/src/Chart/HorizBar.tsx b/packages/react-components/src/Chart/HorizBar.tsx index b34b871927..534153ceb2 100644 --- a/packages/react-components/src/Chart/HorizBar.tsx +++ b/packages/react-components/src/Chart/HorizBar.tsx @@ -87,7 +87,7 @@ function ChartHorizBar ({ aspectRatio = 8, className, max = 100, showLabels = fa if (newJsonValues !== jsonValues) { setState(calculateOptions(aspectRatio, values, newJsonValues, max, showLabels)); } - }, [values]); + }, [aspectRatio, jsonValues, max, showLabels, values]); if (!chartData) { return null; diff --git a/packages/react-components/src/Chart/Line.tsx b/packages/react-components/src/Chart/Line.tsx index a7ee14b15d..5182a455eb 100644 --- a/packages/react-components/src/Chart/Line.tsx +++ b/packages/react-components/src/Chart/Line.tsx @@ -82,7 +82,7 @@ function LineChart ({ className, colors, labels, legends, style, values }: LineP if (newJsonValues !== jsonValues) { setState(calculateOptions(colors, legends, labels, values, newJsonValues)); } - }, [labels, legends, values]); + }, [colors, jsonValues, labels, legends, values]); if (!chartData) { return null; diff --git a/packages/react-components/src/Dropdown.tsx b/packages/react-components/src/Dropdown.tsx index 240a73c258..ad66b55722 100644 --- a/packages/react-components/src/Dropdown.tsx +++ b/packages/react-components/src/Dropdown.tsx @@ -56,6 +56,7 @@ function BaseDropdown