From e97868348bc2541a007719556cbc744ece3d3253 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Sun, 15 Mar 2020 12:11:59 +0100 Subject: [PATCH] React.memo-ize more func. components (#2389) * React.memo-ize more func. components * Rework status display determination * isApiReady && * ApiSigner private class interface * readonly # * Remove isPrimary on council vote --- packages/apps/src/Content/NotFound.tsx | 4 +- packages/apps/src/Content/Status.tsx | 91 ++++++++++--------- packages/apps/src/SideBar/Item.tsx | 6 +- packages/apps/src/WarmUp.tsx | 12 ++- packages/apps/src/modals/Network.tsx | 4 +- packages/page-council/src/Motions/Voting.tsx | 1 - packages/page-council/src/useCounter.ts | 2 +- packages/page-democracy/src/useCounter.ts | 4 +- packages/page-tech-comm/src/useCounter.ts | 2 +- packages/page-treasury/src/useCounter.ts | 2 +- .../react-components/src/Status/index.tsx | 51 +++++++---- packages/react-query/src/BestNumber.tsx | 2 +- packages/react-signer/src/ApiSigner.ts | 14 +-- 13 files changed, 111 insertions(+), 84 deletions(-) diff --git a/packages/apps/src/Content/NotFound.tsx b/packages/apps/src/Content/NotFound.tsx index dbb1c7cb3d..c6cf9ed2e8 100644 --- a/packages/apps/src/Content/NotFound.tsx +++ b/packages/apps/src/Content/NotFound.tsx @@ -10,8 +10,10 @@ type Props = {}; const defaultTo = `/${routing.default}`; -export default function NotFound (): React.ReactElement { +function NotFound (): React.ReactElement { return ( ); } + +export default React.memo(NotFound); diff --git a/packages/apps/src/Content/Status.tsx b/packages/apps/src/Content/Status.tsx index 4a97ce4550..49e3fc8fbc 100644 --- a/packages/apps/src/Content/Status.tsx +++ b/packages/apps/src/Content/Status.tsx @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/camelcase */ // Copyright 2017-2020 @polkadot/apps authors & contributors // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. @@ -24,54 +23,58 @@ interface Props { let prevEventHash: string; -export default function Status ({ optionsAll, queueAction, stqueue, txqueue }: Props): React.ReactElement { +function filterEvents (allAccounts: string[], t: (key: string, opts?: object) => string, optionsAll?: KeyringOptions, events?: EventRecord[]): ActionStatus[] | null { + const eventHash = xxhashAsHex(stringToU8a(JSON.stringify(events))); + + if (!optionsAll || !events || eventHash === prevEventHash) { + return null; + } + + prevEventHash = eventHash; + + return events + .map(({ event: { data, method, section } }): ActionStatus | null => { + if (section === 'balances' && method === 'Transfer') { + const account = data[1].toString(); + + if (allAccounts.includes(account)) { + return { + account, + action: `${section}.${method}`, + status: 'event', + message: t('transfer received') + }; + } + } else if (section === 'democracy') { + const index = data[0].toString(); + + return { + action: `${section}.${method}`, + status: 'event', + message: t('update on #{{index}}', { + replace: { + index + } + }) + }; + } + + return null; + }) + .filter((item): item is ActionStatus => !!item); +} + +function Status ({ optionsAll, queueAction, stqueue, txqueue }: Props): React.ReactElement { const { api, isApiReady } = useApi(); const { allAccounts } = useAccounts(); const { t } = useTranslation(); - const events = useCall(isApiReady ? api.query.system?.events : undefined, []); + const events = useCall(isApiReady && api.query.system?.events, []); useEffect((): void => { - const eventHash = xxhashAsHex(stringToU8a(JSON.stringify(events))); + const filtered = filterEvents(allAccounts, t, optionsAll, events); - if (!optionsAll || eventHash === prevEventHash) { - return; - } - - prevEventHash = eventHash; - - const statusses = events && events - .map(({ event: { data, method, section } }): ActionStatus | null => { - if (section === 'balances' && method === 'Transfer') { - const account = data[1].toString(); - - if (allAccounts.includes(account)) { - return { - account, - action: `${section}.${method}`, - status: 'event', - message: t('transfer received') - }; - } - } else if (section === 'democracy') { - const index = data[0].toString(); - - return { - action: `${section}.${method}`, - status: 'event', - message: t('update on #{{index}}', { - replace: { - index - } - }) - }; - } - - return null; - }) - .filter((item): boolean => !!item) as ActionStatus[]; - - statusses && statusses.length && queueAction(statusses); - }, [events]); + filtered && queueAction(filtered); + }, [allAccounts, events, optionsAll]); return ( ); } + +export default React.memo(Status); diff --git a/packages/apps/src/SideBar/Item.tsx b/packages/apps/src/SideBar/Item.tsx index b521b85a32..9afb305d8a 100644 --- a/packages/apps/src/SideBar/Item.tsx +++ b/packages/apps/src/SideBar/Item.tsx @@ -73,12 +73,12 @@ function checkVisible (name: string, { api, isApiReady, isApiConnected }: ApiPro return notFound.length === 0; } -export default function Item ({ route, isCollapsed, onClick }: Props): React.ReactElement | null { +function Item ({ route, isCollapsed, onClick }: Props): React.ReactElement | 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 : undefined, []); + const sudoKey = useCall(apiProps.isApiReady && apiProps.api.query.sudo?.key, []); const [hasSudo, setHasSudo] = useState(false); const [isVisible, setIsVisible] = useState(false); const count = useCounter(); @@ -149,3 +149,5 @@ export default function Item ({ route, isCollapsed, onClick }: Props): React.Rea ); } + +export default React.memo(Item); diff --git a/packages/apps/src/WarmUp.tsx b/packages/apps/src/WarmUp.tsx index 0e9fbb2c07..c48a4a4db2 100644 --- a/packages/apps/src/WarmUp.tsx +++ b/packages/apps/src/WarmUp.tsx @@ -5,12 +5,12 @@ import React, { useEffect, useState } from 'react'; import { useApi, useCall } from '@polkadot/react-hooks'; -export default function WarmUp (): React.ReactElement { +function WarmUp (): React.ReactElement { const { api, isApiReady } = useApi(); - const fees = useCall(isApiReady && api.derive.balances?.fees, []); - const indexes = useCall(isApiReady && api.derive.accounts?.indexes, []); - const registrars = useCall(isApiReady && api.query.identity?.registrars, []); - const staking = null; // useCall(isApiReady ? api.derive.staking?.overview : undefined, []); + const fees = useCall(isApiReady && api.derive.balances?.fees, []); + const indexes = useCall(isApiReady && api.derive.accounts?.indexes, []); + const registrars = useCall(isApiReady && api.query.identity?.registrars, []); + const staking = null; // useCall(isApiReady && api.derive.staking?.overview, []); const [hasValues, setHasValues] = useState(false); useEffect((): void => { @@ -21,3 +21,5 @@ export default function WarmUp (): React.ReactElement {
); } + +export default React.memo(WarmUp); diff --git a/packages/apps/src/modals/Network.tsx b/packages/apps/src/modals/Network.tsx index e1fc8fe976..cede2be37d 100644 --- a/packages/apps/src/modals/Network.tsx +++ b/packages/apps/src/modals/Network.tsx @@ -13,7 +13,7 @@ interface Props { onClose: () => void; } -export default function NetworkModal ({ className, onClose }: Props): React.ReactElement { +function NetworkModal ({ className, onClose }: Props): React.ReactElement { const { t } = useTranslation(); return ( @@ -30,3 +30,5 @@ export default function NetworkModal ({ className, onClose }: Props): React.Reac ); } + +export default React.memo(NetworkModal); diff --git a/packages/page-council/src/Motions/Voting.tsx b/packages/page-council/src/Motions/Voting.tsx index fd11b9d5a1..80e7881a3b 100644 --- a/packages/page-council/src/Motions/Voting.tsx +++ b/packages/page-council/src/Motions/Voting.tsx @@ -71,7 +71,6 @@ export default function Voting ({ hash, idNumber, isDisabled, members, prime, pr
)} - {alltx.map(renderItem)} - {allst.map(renderStatus)} + {allTx.map(renderItem)} + {allSt.map(renderStatus)} ); } diff --git a/packages/react-query/src/BestNumber.tsx b/packages/react-query/src/BestNumber.tsx index 7feea9793f..b369373a36 100644 --- a/packages/react-query/src/BestNumber.tsx +++ b/packages/react-query/src/BestNumber.tsx @@ -17,7 +17,7 @@ interface Props extends BareProps { export default function BestNumber ({ children, className, label, style, withPound }: Props): React.ReactElement { const { api, isApiReady } = useApi(); - const bestNumber = useCall(isApiReady ? api.derive.chain.bestNumber as any : undefined, []); + const bestNumber = useCall(isApiReady && api.derive.chain.bestNumber, []); return (
{ return new Promise((resolve, reject): void => { - this._queuePayload(payload, (id: number, result: SignerResult | null): void => { + this.#queuePayload(payload, (id: number, result: SignerResult | null): void => { if (result) { resolve(result); } else { @@ -35,9 +35,9 @@ export default class ApiSigner implements Signer { public update (id: number, result: Hash | SubmittableResult): void { if (result instanceof ClassOf(registry, 'Hash')) { - this._queueSetTxStatus(id, 'sent', result.toHex()); + this.#queueSetTxStatus(id, 'sent', result.toHex()); } else { - this._queueSetTxStatus(id, result.status.type.toLowerCase() as QueueTxStatus, status); + this.#queueSetTxStatus(id, result.status.type.toLowerCase() as QueueTxStatus, status); } } }