From d1a2c885a2f96869058160b5c0f743be9aeaf873 Mon Sep 17 00:00:00 2001 From: William O'Beirne Date: Mon, 29 Jan 2018 14:13:46 -0500 Subject: [PATCH] Performance Improvements (Pure components, debounced gas slider) (#899) * PureComponent a ton of non-connected components. * Debounce gas price slider. Keep gas price in state to reflect changes immediately. * PureComponent balance sidebar and swap unconnected components. * Import correct component. * Move debouncing of gas slider to sagas via gasPriceInputIntent action. * Remove console log. * Remove leftover file from merge. --- .../transaction/actionCreators/fields.ts | 9 ++++ .../actions/transaction/actionTypes/fields.ts | 5 +++ common/actions/transaction/constants.ts | 1 + common/components/AlphaAgreement/index.tsx | 2 +- .../TokenBalances/AddCustomTokenForm.tsx | 2 +- .../BalanceSidebar/TokenBalances/Balances.tsx | 2 +- .../BalanceSidebar/TokenBalances/TokenRow.tsx | 2 +- common/components/Footer/PreFooter.tsx | 2 +- common/components/Footer/index.tsx | 2 +- .../Header/components/CustomNodeModal.tsx | 2 +- .../Header/components/Navigation.tsx | 4 +- .../Header/components/NavigationLink.tsx | 2 +- common/components/Header/index.tsx | 4 +- common/components/SubTabs/index.tsx | 2 +- .../TXMetaDataPanel/TXMetaDataPanel.tsx | 25 ++++++++++- .../components/AdvancedGas.tsx | 1 + .../TXMetaDataPanel/components/FeeSummary.tsx | 14 ++++--- .../TXMetaDataPanel/components/SimpleGas.tsx | 6 +-- .../components/DeterministicWalletsModal.tsx | 2 +- .../components/DigitalBitbox.tsx | 2 +- .../WalletDecrypt/components/Keystore.tsx | 4 +- .../WalletDecrypt/components/LedgerNano.tsx | 4 +- .../WalletDecrypt/components/Mnemonic.tsx | 4 +- .../WalletDecrypt/components/PrivateKey.tsx | 4 +- .../WalletDecrypt/components/Trezor.tsx | 4 +- .../WalletDecrypt/components/ViewOnly.tsx | 4 +- .../WalletDecrypt/components/Web3.tsx | 41 ++++++++----------- common/components/ui/ColorDropdown.tsx | 4 +- common/components/ui/Dropdown.tsx | 4 +- common/components/ui/DropdownShell.tsx | 4 +- common/components/ui/Expandable.tsx | 4 +- common/components/ui/Modal.tsx | 4 +- common/components/ui/QRCode.tsx | 2 +- common/components/ui/SimpleDropdown.tsx | 4 +- common/components/ui/SimpleSelect.tsx | 4 +- common/components/ui/SwapDropdown.tsx | 4 +- .../SendTransaction/components/WalletInfo.tsx | 2 +- .../Tabs/Swap/components/BitcoinQR.tsx | 4 +- .../Tabs/Swap/components/CurrencySwap.tsx | 4 +- .../Tabs/Swap/components/CurrentRates.tsx | 4 +- .../Tabs/Swap/components/PartThree.tsx | 4 +- .../Tabs/Swap/components/PaymentInfo.tsx | 4 +- .../Tabs/Swap/components/ReceivingAddress.tsx | 4 +- .../Tabs/Swap/components/ShapeshiftBanner.tsx | 4 +- .../Tabs/Swap/components/SupportFooter.tsx | 2 +- .../Tabs/Swap/components/SwapInfoHeader.tsx | 4 +- .../Swap/components/SwapInfoHeaderTitle.tsx | 4 +- .../Tabs/Swap/components/SwapProgress.tsx | 4 +- common/libs/units.ts | 2 +- .../reducers/transaction/network/network.ts | 29 +++++++++++-- .../reducers/transaction/network/typings.ts | 1 + common/sagas/transaction/fields/fields.ts | 16 ++++++-- common/selectors/transaction/fields.ts | 2 + 53 files changed, 177 insertions(+), 107 deletions(-) diff --git a/common/actions/transaction/actionCreators/fields.ts b/common/actions/transaction/actionCreators/fields.ts index 0ac1a4b5..e64c15aa 100644 --- a/common/actions/transaction/actionCreators/fields.ts +++ b/common/actions/transaction/actionCreators/fields.ts @@ -6,6 +6,7 @@ import { SetValueFieldAction, InputGasLimitAction, InputGasPriceAction, + InputGasPriceIntentAction, InputDataAction, InputNonceAction, ResetAction, @@ -25,6 +26,12 @@ const inputGasPrice = (payload: InputGasPriceAction['payload']) => ({ payload }); +type TInputGasPriceIntent = typeof inputGasPrice; +const inputGasPriceIntent = (payload: InputGasPriceIntentAction['payload']) => ({ + type: TypeKeys.GAS_PRICE_INPUT_INTENT, + payload +}); + type TInputNonce = typeof inputNonce; const inputNonce = (payload: InputNonceAction['payload']) => ({ type: TypeKeys.NONCE_INPUT, @@ -79,6 +86,7 @@ const reset = (): ResetAction => ({ type: TypeKeys.RESET }); export { TInputGasLimit, TInputGasPrice, + TInputGasPriceIntent, TInputNonce, TInputData, TSetGasLimitField, @@ -90,6 +98,7 @@ export { TReset, inputGasLimit, inputGasPrice, + inputGasPriceIntent, inputNonce, inputData, setGasLimitField, diff --git a/common/actions/transaction/actionTypes/fields.ts b/common/actions/transaction/actionTypes/fields.ts index c390844b..a4183a94 100644 --- a/common/actions/transaction/actionTypes/fields.ts +++ b/common/actions/transaction/actionTypes/fields.ts @@ -10,6 +10,10 @@ interface InputGasPriceAction { type: TypeKeys.GAS_PRICE_INPUT; payload: string; } +interface InputGasPriceIntentAction { + type: TypeKeys.GAS_PRICE_INPUT_INTENT; + payload: string; +} interface InputDataAction { type: TypeKeys.DATA_FIELD_INPUT; payload: string; @@ -84,6 +88,7 @@ type FieldAction = export { InputGasLimitAction, InputGasPriceAction, + InputGasPriceIntentAction, InputDataAction, InputNonceAction, SetGasLimitFieldAction, diff --git a/common/actions/transaction/constants.ts b/common/actions/transaction/constants.ts index 8c8008d7..4d08f6c0 100644 --- a/common/actions/transaction/constants.ts +++ b/common/actions/transaction/constants.ts @@ -30,6 +30,7 @@ export enum TypeKeys { DATA_FIELD_INPUT = 'DATA_FIELD_INPUT', GAS_LIMIT_INPUT = 'GAS_LIMIT_INPUT', GAS_PRICE_INPUT = 'GAS_PRICE_INPUT', + GAS_PRICE_INPUT_INTENT = 'GAS_PRICE_INPUT_INTENT', NONCE_INPUT = 'NONCE_INPUT', DATA_FIELD_SET = 'DATA_FIELD_SET', diff --git a/common/components/AlphaAgreement/index.tsx b/common/components/AlphaAgreement/index.tsx index cce81bbc..d498655c 100644 --- a/common/components/AlphaAgreement/index.tsx +++ b/common/components/AlphaAgreement/index.tsx @@ -7,7 +7,7 @@ interface State { isFading: boolean; hasAcknowledged: boolean; } -export default class AlphaAgreement extends React.Component<{}, State> { +export default class AlphaAgreement extends React.PureComponent<{}, State> { public state = { hasAcknowledged: !!localStorage.getItem(LS_KEY), isFading: false diff --git a/common/components/BalanceSidebar/TokenBalances/AddCustomTokenForm.tsx b/common/components/BalanceSidebar/TokenBalances/AddCustomTokenForm.tsx index e14c30a2..74d4ac11 100644 --- a/common/components/BalanceSidebar/TokenBalances/AddCustomTokenForm.tsx +++ b/common/components/BalanceSidebar/TokenBalances/AddCustomTokenForm.tsx @@ -23,7 +23,7 @@ interface State { decimal: string; } -export default class AddCustomTokenForm extends React.Component { +export default class AddCustomTokenForm extends React.PureComponent { public state: State = { tokenSymbolLookup: {}, address: '', diff --git a/common/components/BalanceSidebar/TokenBalances/Balances.tsx b/common/components/BalanceSidebar/TokenBalances/Balances.tsx index e8f08c7c..27cc9ef7 100644 --- a/common/components/BalanceSidebar/TokenBalances/Balances.tsx +++ b/common/components/BalanceSidebar/TokenBalances/Balances.tsx @@ -19,7 +19,7 @@ interface State { trackedTokens: { [symbol: string]: boolean }; showCustomTokenForm: boolean; } -export default class TokenBalances extends React.Component { +export default class TokenBalances extends React.PureComponent { public state = { trackedTokens: {}, showCustomTokenForm: false diff --git a/common/components/BalanceSidebar/TokenBalances/TokenRow.tsx b/common/components/BalanceSidebar/TokenBalances/TokenRow.tsx index d82d67e4..a638e495 100644 --- a/common/components/BalanceSidebar/TokenBalances/TokenRow.tsx +++ b/common/components/BalanceSidebar/TokenBalances/TokenRow.tsx @@ -19,7 +19,7 @@ interface State { showLongBalance: boolean; } -export default class TokenRow extends React.Component { +export default class TokenRow extends React.PureComponent { public state = { showLongBalance: false }; diff --git a/common/components/Footer/PreFooter.tsx b/common/components/Footer/PreFooter.tsx index e8fe76fe..9a86f364 100644 --- a/common/components/Footer/PreFooter.tsx +++ b/common/components/Footer/PreFooter.tsx @@ -1,7 +1,7 @@ import React from 'react'; import './PreFooter.scss'; -const PreFooter = () => { +const PreFooter: React.SFC<{}> = () => { return (
diff --git a/common/components/Footer/index.tsx b/common/components/Footer/index.tsx index f92ab839..e772beed 100644 --- a/common/components/Footer/index.tsx +++ b/common/components/Footer/index.tsx @@ -108,7 +108,7 @@ interface State { isOpen: boolean; } -export default class Footer extends React.Component { +export default class Footer extends React.PureComponent { constructor(props: Props) { super(props); this.state = { isOpen: false }; diff --git a/common/components/Header/components/CustomNodeModal.tsx b/common/components/Header/components/CustomNodeModal.tsx index 0f78b798..a228d27c 100644 --- a/common/components/Header/components/CustomNodeModal.tsx +++ b/common/components/Header/components/CustomNodeModal.tsx @@ -36,7 +36,7 @@ interface State { password: string; } -export default class CustomNodeModal extends React.Component { +export default class CustomNodeModal extends React.PureComponent { public state: State = { name: '', url: '', diff --git a/common/components/Header/components/Navigation.tsx b/common/components/Header/components/Navigation.tsx index 103070f2..22cb8c9e 100644 --- a/common/components/Header/components/Navigation.tsx +++ b/common/components/Header/components/Navigation.tsx @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React, { PureComponent } from 'react'; import NavigationLink from './NavigationLink'; import { knowledgeBaseURL } from 'config'; import './Navigation.scss'; @@ -58,7 +58,7 @@ interface BorderStyle { borderTopColor?: string; } -export default class Navigation extends Component { +export default class Navigation extends PureComponent { public state = { showLeftArrow: false, showRightArrow: false diff --git a/common/components/Header/components/NavigationLink.tsx b/common/components/Header/components/NavigationLink.tsx index 42ca117e..8e841880 100644 --- a/common/components/Header/components/NavigationLink.tsx +++ b/common/components/Header/components/NavigationLink.tsx @@ -10,7 +10,7 @@ interface Props extends RouteComponentProps<{}> { isHomepage: boolean; } -class NavigationLink extends React.Component { +class NavigationLink extends React.PureComponent { public render() { const { link, location, isHomepage } = this.props; const isExternalLink = link.to.includes('http'); diff --git a/common/components/Header/index.tsx b/common/components/Header/index.tsx index 5ead46cd..96fcc9de 100644 --- a/common/components/Header/index.tsx +++ b/common/components/Header/index.tsx @@ -7,7 +7,7 @@ import { } from 'actions/config'; import logo from 'assets/images/logo-myetherwallet.svg'; import { Dropdown, ColorDropdown } from 'components/ui'; -import React, { Component } from 'react'; +import React, { PureComponent } from 'react'; import classnames from 'classnames'; import { Link } from 'react-router-dom'; import { TSetGasPriceField } from 'actions/transaction'; @@ -49,7 +49,7 @@ interface State { isAddingCustomNode: boolean; } -export default class Header extends Component { +export default class Header extends PureComponent { public state = { isAddingCustomNode: false }; diff --git a/common/components/SubTabs/index.tsx b/common/components/SubTabs/index.tsx index 0dc0765d..65b92a2f 100644 --- a/common/components/SubTabs/index.tsx +++ b/common/components/SubTabs/index.tsx @@ -14,7 +14,7 @@ interface Props { match: RouteComponentProps<{}>['match']; } -export default class SubTabs extends React.Component { +export default class SubTabs extends React.PureComponent { public render() { const { tabs, match } = this.props; const currentPath = match.url; diff --git a/common/components/TXMetaDataPanel/TXMetaDataPanel.tsx b/common/components/TXMetaDataPanel/TXMetaDataPanel.tsx index 17b89254..fe63ad46 100644 --- a/common/components/TXMetaDataPanel/TXMetaDataPanel.tsx +++ b/common/components/TXMetaDataPanel/TXMetaDataPanel.tsx @@ -1,9 +1,12 @@ import React from 'react'; +import BN from 'bn.js'; import { translateRaw } from 'translations'; import { connect } from 'react-redux'; import { inputGasPrice, TInputGasPrice, + inputGasPriceIntent, + TInputGasPriceIntent, getNonceRequested, TGetNonceRequested, reset, @@ -12,6 +15,7 @@ import { import { fetchCCRates, TFetchCCRates } from 'actions/rates'; import { getNetworkConfig, getOffline } from 'selectors/config'; import { AppState } from 'reducers'; +import { Units } from 'libs/units'; import SimpleGas from './components/SimpleGas'; import AdvancedGas, { AdvancedOptions } from './components/AdvancedGas'; import './TXMetaDataPanel.scss'; @@ -27,6 +31,7 @@ interface StateProps { interface DispatchProps { inputGasPrice: TInputGasPrice; + inputGasPriceIntent: TInputGasPriceIntent; fetchCCRates: TFetchCCRates; getNonceRequested: TGetNonceRequested; reset: TReset; @@ -47,6 +52,7 @@ interface OwnProps { type Props = DispatchProps & OwnProps & StateProps; interface State { + gasPrice: AppState['transaction']['fields']['gasPrice']; sliderState: SliderStates; } @@ -56,6 +62,7 @@ class TXMetaDataPanel extends React.Component { }; public state: State = { + gasPrice: this.props.gasPrice, sliderState: (this.props as DefaultProps).initialState }; @@ -71,10 +78,14 @@ class TXMetaDataPanel extends React.Component { if (this.props.offline && !nextProps.offline) { this.props.fetchCCRates([this.props.network.unit]); } + if (this.props.gasPrice !== nextProps.gasPrice) { + this.setState({ gasPrice: nextProps.gasPrice }); + } } public render() { - const { offline, disableToggle, gasPrice, advancedGasOptions, className = '' } = this.props; + const { offline, disableToggle, advancedGasOptions, className = '' } = this.props; + const { gasPrice } = this.state; const showAdvanced = this.state.sliderState === 'advanced' || offline; return (
@@ -85,7 +96,7 @@ class TXMetaDataPanel extends React.Component { options={advancedGasOptions} /> ) : ( - + )} {!offline && @@ -107,6 +118,15 @@ class TXMetaDataPanel extends React.Component { private toggleAdvanced = () => { this.setState({ sliderState: this.state.sliderState === 'advanced' ? 'simple' : 'advanced' }); }; + + private handleGasPriceInput = (raw: string) => { + const gasBn = new BN(raw); + const value = gasBn.mul(new BN(Units.gwei)); + this.setState({ + gasPrice: { raw, value } + }); + this.props.inputGasPriceIntent(raw); + }; } function mapStateToProps(state: AppState): StateProps { @@ -119,6 +139,7 @@ function mapStateToProps(state: AppState): StateProps { export default connect(mapStateToProps, { inputGasPrice, + inputGasPriceIntent, fetchCCRates, getNonceRequested, reset diff --git a/common/components/TXMetaDataPanel/components/AdvancedGas.tsx b/common/components/TXMetaDataPanel/components/AdvancedGas.tsx index 0e58a33f..a20d1e8b 100644 --- a/common/components/TXMetaDataPanel/components/AdvancedGas.tsx +++ b/common/components/TXMetaDataPanel/components/AdvancedGas.tsx @@ -108,6 +108,7 @@ class AdvancedGas extends React.Component { {feeSummary && (
( {gasPriceWei} * {gasLimit} = {fee} {usd && ~= ${usd} USD} diff --git a/common/components/TXMetaDataPanel/components/FeeSummary.tsx b/common/components/TXMetaDataPanel/components/FeeSummary.tsx index 2afc4319..4c68f504 100644 --- a/common/components/TXMetaDataPanel/components/FeeSummary.tsx +++ b/common/components/TXMetaDataPanel/components/FeeSummary.tsx @@ -14,17 +14,20 @@ interface RenderData { usd: React.ReactElement | null; } -interface Props { - // Redux props - gasPrice: AppState['transaction']['fields']['gasPrice']; +interface ReduxStateProps { gasLimit: AppState['transaction']['fields']['gasLimit']; rates: AppState['rates']['rates']; network: AppState['config']['network']; isOffline: AppState['config']['offline']; - // Component props +} + +interface OwnProps { + gasPrice: AppState['transaction']['fields']['gasPrice']; render(data: RenderData): React.ReactElement | string; } +type Props = OwnProps & ReduxStateProps; + class FeeSummary extends React.Component { public render() { const { gasPrice, gasLimit, rates, network, isOffline } = this.props; @@ -67,9 +70,8 @@ class FeeSummary extends React.Component { } } -function mapStateToProps(state: AppState) { +function mapStateToProps(state: AppState): ReduxStateProps { return { - gasPrice: state.transaction.fields.gasPrice, gasLimit: state.transaction.fields.gasLimit, rates: state.rates.rates, network: getNetworkConfig(state), diff --git a/common/components/TXMetaDataPanel/components/SimpleGas.tsx b/common/components/TXMetaDataPanel/components/SimpleGas.tsx index 7623273e..cf1ce983 100644 --- a/common/components/TXMetaDataPanel/components/SimpleGas.tsx +++ b/common/components/TXMetaDataPanel/components/SimpleGas.tsx @@ -3,7 +3,6 @@ import Slider from 'rc-slider'; import translate, { translateRaw } from 'translations'; import { gasPriceDefaults } from 'config'; import FeeSummary from './FeeSummary'; -import { TInputGasPrice } from 'actions/transaction'; import './SimpleGas.scss'; import { AppState } from 'reducers'; import { getGasLimitEstimationTimedOut } from 'selectors/transaction'; @@ -13,7 +12,7 @@ import { getIsWeb3Node } from 'selectors/config'; interface OwnProps { gasPrice: AppState['transaction']['fields']['gasPrice']; - inputGasPrice: TInputGasPrice; + inputGasPrice(rawGas: string); } interface StateProps { @@ -41,7 +40,7 @@ class SimpleGas extends React.Component {

{isWeb3Node - ? "Couldn't calculate gas limit, if you know what your doing, try setting manually in Advanced settings" + ? "Couldn't calculate gas limit, if you know what you're doing, try setting manually in Advanced settings" : "Couldn't calculate gas limit, try switching nodes"}

@@ -62,6 +61,7 @@ class SimpleGas extends React.Component {
( {fee} {usd && / ${usd}} diff --git a/common/components/WalletDecrypt/components/DeterministicWalletsModal.tsx b/common/components/WalletDecrypt/components/DeterministicWalletsModal.tsx index a0b1aef3..6a1107aa 100644 --- a/common/components/WalletDecrypt/components/DeterministicWalletsModal.tsx +++ b/common/components/WalletDecrypt/components/DeterministicWalletsModal.tsx @@ -60,7 +60,7 @@ const customDPath: DPath = { value: 'custom' }; -class DeterministicWalletsModalClass extends React.Component { +class DeterministicWalletsModalClass extends React.PureComponent { public state: State = { selectedAddress: '', selectedAddrIndex: 0, diff --git a/common/components/WalletDecrypt/components/DigitalBitbox.tsx b/common/components/WalletDecrypt/components/DigitalBitbox.tsx index 6b5dd911..48b98fa0 100644 --- a/common/components/WalletDecrypt/components/DigitalBitbox.tsx +++ b/common/components/WalletDecrypt/components/DigitalBitbox.tsx @@ -1,6 +1,6 @@ import React from 'react'; -export class DigitalBitboxDecrypt extends React.Component<{}, {}> { +export class DigitalBitboxDecrypt extends React.PureComponent<{}, {}> { public render() { return Not yet implemented; } diff --git a/common/components/WalletDecrypt/components/Keystore.tsx b/common/components/WalletDecrypt/components/Keystore.tsx index 0b938124..22770b3f 100644 --- a/common/components/WalletDecrypt/components/Keystore.tsx +++ b/common/components/WalletDecrypt/components/Keystore.tsx @@ -1,5 +1,5 @@ import { isKeystorePassRequired } from 'libs/wallet'; -import React, { Component } from 'react'; +import React, { PureComponent } from 'react'; import translate, { translateRaw } from 'translations'; import Spinner from 'components/ui/Spinner'; import { TShowNotification } from 'actions/notifications'; @@ -25,7 +25,7 @@ function isValidFile(rawFile: File): boolean { return fileType === '' || fileType === 'application/json'; } -export class KeystoreDecrypt extends Component { +export class KeystoreDecrypt extends PureComponent { public props: { value: KeystoreValue; isWalletPending: boolean; diff --git a/common/components/WalletDecrypt/components/LedgerNano.tsx b/common/components/WalletDecrypt/components/LedgerNano.tsx index af7ef2c4..5dbadd11 100644 --- a/common/components/WalletDecrypt/components/LedgerNano.tsx +++ b/common/components/WalletDecrypt/components/LedgerNano.tsx @@ -1,5 +1,5 @@ import './LedgerNano.scss'; -import React, { Component } from 'react'; +import React, { PureComponent } from 'react'; import translate, { translateRaw } from 'translations'; import DeterministicWalletsModal from './DeterministicWalletsModal'; import { LedgerWallet } from 'libs/wallet'; @@ -31,7 +31,7 @@ interface State { type Props = OwnProps & StateProps; -class LedgerNanoSDecryptClass extends Component { +class LedgerNanoSDecryptClass extends PureComponent { public state: State = { publicKey: '', chainCode: '', diff --git a/common/components/WalletDecrypt/components/Mnemonic.tsx b/common/components/WalletDecrypt/components/Mnemonic.tsx index eadb0eb2..5a76f814 100644 --- a/common/components/WalletDecrypt/components/Mnemonic.tsx +++ b/common/components/WalletDecrypt/components/Mnemonic.tsx @@ -1,5 +1,5 @@ import { mnemonicToSeed, validateMnemonic } from 'bip39'; -import React, { Component } from 'react'; +import React, { PureComponent } from 'react'; import translate, { translateRaw } from 'translations'; import DeterministicWalletsModal from './DeterministicWalletsModal'; import { formatMnemonic } from 'utils/formatters'; @@ -27,7 +27,7 @@ interface State { dPath: string; } -class MnemonicDecryptClass extends Component { +class MnemonicDecryptClass extends PureComponent { public state: State = { phrase: '', formattedPhrase: '', diff --git a/common/components/WalletDecrypt/components/PrivateKey.tsx b/common/components/WalletDecrypt/components/PrivateKey.tsx index 5c4bb833..92a76469 100644 --- a/common/components/WalletDecrypt/components/PrivateKey.tsx +++ b/common/components/WalletDecrypt/components/PrivateKey.tsx @@ -1,6 +1,6 @@ import { isValidEncryptedPrivKey, isValidPrivKey } from 'libs/validators'; import { stripHexPrefix } from 'libs/values'; -import React, { Component } from 'react'; +import React, { PureComponent } from 'react'; import translate, { translateRaw } from 'translations'; import { TogglablePassword } from 'components'; @@ -45,7 +45,7 @@ interface Props { onUnlock(): void; } -export class PrivateKeyDecrypt extends Component { +export class PrivateKeyDecrypt extends PureComponent { public render() { const { key, password } = this.props.value; const { isValidPkey, isPassRequired } = validatePkeyAndPass(key, password); diff --git a/common/components/WalletDecrypt/components/Trezor.tsx b/common/components/WalletDecrypt/components/Trezor.tsx index c74528f0..ff351604 100644 --- a/common/components/WalletDecrypt/components/Trezor.tsx +++ b/common/components/WalletDecrypt/components/Trezor.tsx @@ -1,5 +1,5 @@ import { TrezorWallet, TREZOR_MINIMUM_FIRMWARE } from 'libs/wallet'; -import React, { Component } from 'react'; +import React, { PureComponent } from 'react'; import translate, { translateRaw } from 'translations'; import TrezorConnect from 'vendor/trezor-connect'; import DeterministicWalletsModal from './DeterministicWalletsModal'; @@ -32,7 +32,7 @@ interface State { type Props = OwnProps & StateProps; -class TrezorDecryptClass extends Component { +class TrezorDecryptClass extends PureComponent { public state: State = { publicKey: '', chainCode: '', diff --git a/common/components/WalletDecrypt/components/ViewOnly.tsx b/common/components/WalletDecrypt/components/ViewOnly.tsx index 4504c71f..f463d5e3 100644 --- a/common/components/WalletDecrypt/components/ViewOnly.tsx +++ b/common/components/WalletDecrypt/components/ViewOnly.tsx @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React, { PureComponent } from 'react'; import translate from 'translations'; import { donationAddressMap } from 'config'; import { isValidETHAddress } from 'libs/validators'; @@ -12,7 +12,7 @@ interface State { address: string; } -export class ViewOnlyDecrypt extends Component { +export class ViewOnlyDecrypt extends PureComponent { public state = { address: '' }; diff --git a/common/components/WalletDecrypt/components/Web3.tsx b/common/components/WalletDecrypt/components/Web3.tsx index e4a67694..1c6a7906 100644 --- a/common/components/WalletDecrypt/components/Web3.tsx +++ b/common/components/WalletDecrypt/components/Web3.tsx @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React from 'react'; import translate from 'translations'; import { NewTabLink } from 'components/ui'; import './Web3.scss'; @@ -7,27 +7,20 @@ interface Props { onUnlock(): void; } -export class Web3Decrypt extends Component { - public render() { - return ( -
-
- -
+export const Web3Decrypt: React.SFC = ({ onUnlock }) => ( +
+
+ +
-
- -
-
- ); - } -} +
+ +
+
+); diff --git a/common/components/ui/ColorDropdown.tsx b/common/components/ui/ColorDropdown.tsx index 5a32c55a..32da87cc 100644 --- a/common/components/ui/ColorDropdown.tsx +++ b/common/components/ui/ColorDropdown.tsx @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React, { PureComponent } from 'react'; import classnames from 'classnames'; import DropdownShell from './DropdownShell'; import removeIcon from 'assets/images/icon-remove.svg'; @@ -25,7 +25,7 @@ interface Props { onChange(value: T): void; } -export default class ColorDropdown extends Component, {}> { +export default class ColorDropdown extends PureComponent, {}> { private dropdownShell: DropdownShell | null; public render() { diff --git a/common/components/ui/Dropdown.tsx b/common/components/ui/Dropdown.tsx index 289a2488..29b92e53 100644 --- a/common/components/ui/Dropdown.tsx +++ b/common/components/ui/Dropdown.tsx @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React, { PureComponent } from 'react'; import classnames from 'classnames'; import DropdownShell from './DropdownShell'; @@ -19,7 +19,7 @@ interface State { search: string; } -export default class DropdownComponent extends Component, State> { +export default class DropdownComponent extends PureComponent, State> { public state = { search: '' }; diff --git a/common/components/ui/DropdownShell.tsx b/common/components/ui/DropdownShell.tsx index 35f10285..ebc97e4f 100644 --- a/common/components/ui/DropdownShell.tsx +++ b/common/components/ui/DropdownShell.tsx @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React, { PureComponent } from 'react'; import classnames from 'classnames'; interface Props { @@ -14,7 +14,7 @@ interface State { expanded: boolean; } -export default class DropdownComponent extends Component { +export default class DropdownComponent extends PureComponent { public static defaultProps = { color: 'default', size: 'sm' diff --git a/common/components/ui/Expandable.tsx b/common/components/ui/Expandable.tsx index b785c90d..62864dbe 100644 --- a/common/components/ui/Expandable.tsx +++ b/common/components/ui/Expandable.tsx @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React, { PureComponent } from 'react'; export type ExpandHandler = (ev: React.FormEvent) => void; @@ -13,7 +13,7 @@ interface State { const initialState: State = { expanded: false }; -export class Expandable extends Component { +export class Expandable extends PureComponent { public state: State = initialState; public render() { diff --git a/common/components/ui/Modal.tsx b/common/components/ui/Modal.tsx index 4f7a1e87..b9b056db 100644 --- a/common/components/ui/Modal.tsx +++ b/common/components/ui/Modal.tsx @@ -1,5 +1,5 @@ import closeIcon from 'assets/images/icon-x.svg'; -import React, { Component } from 'react'; +import React, { PureComponent } from 'react'; import './Modal.scss'; export interface IButton { @@ -17,7 +17,7 @@ interface Props { handleClose?(): void; } -export default class Modal extends Component { +export default class Modal extends PureComponent { private modalContent: HTMLElement | null = null; public componentDidMount() { diff --git a/common/components/ui/QRCode.tsx b/common/components/ui/QRCode.tsx index 1e295d7a..21b7f50f 100644 --- a/common/components/ui/QRCode.tsx +++ b/common/components/ui/QRCode.tsx @@ -13,7 +13,7 @@ interface State { qr?: string; } -export default class QRCode extends React.Component { +export default class QRCode extends React.PureComponent { public state: State = {}; public componentWillMount() { // Start generating QR codes immediately diff --git a/common/components/ui/SimpleDropdown.tsx b/common/components/ui/SimpleDropdown.tsx index 063a4c94..4299c521 100644 --- a/common/components/ui/SimpleDropdown.tsx +++ b/common/components/ui/SimpleDropdown.tsx @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React, { PureComponent } from 'react'; import Dropdown from './Dropdown'; interface Props { @@ -8,7 +8,7 @@ interface Props { onChange(value: string): void; } -export default class SimpleDropdown extends Component { +export default class SimpleDropdown extends PureComponent { public render() { const { options, value, onChange, ariaLabel } = this.props; diff --git a/common/components/ui/SimpleSelect.tsx b/common/components/ui/SimpleSelect.tsx index 95758ae7..cffe21ac 100644 --- a/common/components/ui/SimpleSelect.tsx +++ b/common/components/ui/SimpleSelect.tsx @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React, { PureComponent } from 'react'; interface Props { value?: string; @@ -6,7 +6,7 @@ interface Props { onChange(event: React.FormEvent): void; } -export default class SimpleSelect extends Component { +export default class SimpleSelect extends PureComponent { public render() { return (