From 3d1b5062fe6472a25d69832841257c0a746b4222 Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Thu, 22 Dec 2022 21:07:51 +0100 Subject: [PATCH] Improve `SignatureRequest` performance (#17052) * Improve SignatureRequestData performance * Memoize more selectors --- .../signature-request-data.js | 18 +++++++++++----- .../signature-request.component.js | 11 ++++++++-- .../decoding/address/address.component.js | 8 +++---- ui/selectors/selectors.js | 21 +++++++++++++++++++ 4 files changed, 47 insertions(+), 11 deletions(-) diff --git a/ui/components/app/signature-request/signature-request-data/signature-request-data.js b/ui/components/app/signature-request/signature-request-data/signature-request-data.js index 6685f1c56..0f099283b 100644 --- a/ui/components/app/signature-request/signature-request-data/signature-request-data.js +++ b/ui/components/app/signature-request/signature-request-data/signature-request-data.js @@ -1,7 +1,11 @@ -import React from 'react'; +import React, { memo } from 'react'; import { useSelector } from 'react-redux'; +import { isEqual } from 'lodash'; import PropTypes from 'prop-types'; -import { getMetaMaskIdentities, getAccountName } from '../../../../selectors'; +import { + getMemoizedMetaMaskIdentities, + getAccountName, +} from '../../../../selectors'; import Address from '../../transaction-decoding/components/decoding/address'; import { isValidHexAddress, @@ -16,15 +20,15 @@ import { TYPOGRAPHY, } from '../../../../helpers/constants/design-system'; -export default function SignatureRequestData({ data }) { - const identities = useSelector(getMetaMaskIdentities); +function SignatureRequestData({ data }) { + const identities = useSelector(getMemoizedMetaMaskIdentities); return ( {Object.entries(data).map(([label, value], i) => ( { + return isEqual(prevProps.data, nextProps.data); +}); diff --git a/ui/components/app/signature-request/signature-request.component.js b/ui/components/app/signature-request/signature-request.component.js index fde4acd51..a55e595ba 100644 --- a/ui/components/app/signature-request/signature-request.component.js +++ b/ui/components/app/signature-request/signature-request.component.js @@ -1,4 +1,5 @@ import React, { PureComponent } from 'react'; +import { memoize } from 'lodash'; import PropTypes from 'prop-types'; import LedgerInstructionField from '../ledger-instruction-field'; import { sanitizeMessage, getURLHostName } from '../../../helpers/utils/util'; @@ -107,6 +108,12 @@ export default class SignatureRequest extends PureComponent { } } + memoizedParseMessage = memoize((data) => { + const { message, domain = {}, primaryType, types } = JSON.parse(data); + const sanitizedMessage = sanitizeMessage(message, primaryType, types); + return { sanitizedMessage, domain }; + }); + render() { const { txData: { @@ -126,8 +133,8 @@ export default class SignatureRequest extends PureComponent { conversionRate, nativeCurrency, } = this.props; - const { message, domain = {}, primaryType, types } = JSON.parse(data); const { trackEvent } = this.context; + const { sanitizedMessage, domain } = this.memoizedParseMessage(data); const currentNetwork = this.getNetworkName(); @@ -236,7 +243,7 @@ export default class SignatureRequest extends PureComponent { ) : null} this.setState({ hasScrolledMessage: true })} setMessageRootRef={this.setMessageRootRef.bind(this)} messageRootRef={this.messageRootRef} diff --git a/ui/components/app/transaction-decoding/components/decoding/address/address.component.js b/ui/components/app/transaction-decoding/components/decoding/address/address.component.js index ddb4d5cd7..9b576b5b3 100644 --- a/ui/components/app/transaction-decoding/components/decoding/address/address.component.js +++ b/ui/components/app/transaction-decoding/components/decoding/address/address.component.js @@ -6,8 +6,8 @@ import { shortenAddress } from '../../../../../../helpers/utils/util'; import Identicon from '../../../../../ui/identicon'; import { useI18nContext } from '../../../../../../hooks/useI18nContext'; import { - getMetadataContractName, - getAddressBook, + getMemoizedMetadataContractName, + getMemoizedAddressBook, } from '../../../../../../selectors'; import NicknamePopovers from '../../../../modals/nickname-popovers'; @@ -21,14 +21,14 @@ const Address = ({ const t = useI18nContext(); const [showNicknamePopovers, setShowNicknamePopovers] = useState(false); - const addressBook = useSelector(getAddressBook); + const addressBook = useSelector(getMemoizedAddressBook); const addressBookEntryObject = addressBook.find( (entry) => entry.address.toLowerCase() === checksummedRecipientAddress.toLowerCase(), ); const recipientNickname = addressBookEntryObject?.name; const recipientMetadataName = useSelector((state) => - getMetadataContractName(state, checksummedRecipientAddress), + getMemoizedMetadataContractName(state, checksummedRecipientAddress), ); const recipientToRender = addressOnly diff --git a/ui/selectors/selectors.js b/ui/selectors/selectors.js index 7472ebc05..53d2a4cfb 100644 --- a/ui/selectors/selectors.js +++ b/ui/selectors/selectors.js @@ -814,6 +814,27 @@ export function getShowWhatsNewPopup(state) { const createDeepEqualSelector = createSelectorCreator(defaultMemoize, isEqual); +export const getMemoizedMetaMaskIdentities = createDeepEqualSelector( + getMetaMaskIdentities, + (identities) => identities, +); + +export const getMemoizedAddressBook = createDeepEqualSelector( + getAddressBook, + (addressBook) => addressBook, +); + +export const getMemoizedMetadataContractName = createDeepEqualSelector( + getTokenList, + (_tokenList, address) => address, + (tokenList, address) => { + const entry = Object.values(tokenList).find((identity) => + isEqualCaseInsensitive(identity.address, toChecksumHexAddress(address)), + ); + return entry && entry.name !== '' ? entry.name : ''; + }, +); + export const getUnapprovedTransactions = (state) => state.metamask.unapprovedTxs;