Skip to content

perf(6402): clear set-state-in-effect in platform UI and assets - #45423

Draft
DDDDDanica wants to merge 1 commit into
mainfrom
perf/6402-sse-platform-assets
Draft

perf(6402): clear set-state-in-effect in platform UI and assets#45423
DDDDDanica wants to merge 1 commit into
mainfrom
perf/6402-sse-platform-assets

Conversation

@DDDDDanica

@DDDDDanica DDDDDanica commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Description

Part of MetaMask-planning#6402 subtask 1: clear react-hooks/set-state-in-effect warnings.

What this cleanup does: React warns when setState runs synchronously inside a useEffect, because that forces an extra render pass (You Might Not Need an Effect). These changes replace prop→state syncing in effects with render-time updates or derived values, and keep effects for real external sync only.

Scope: shared platform UI hooks/components/pages, plus NFT full-image.

Changelog

CHANGELOG entry: null

Related issues

Part of: MetaMask/MetaMask-planning#6402

Manual testing steps

  1. Spot-check home/token/contact/network pages touched by this PR.
  2. Open NFT full image view; confirm fade/load still works.
  3. Confirm shared hooks (theme, debounce, token tracker) don’t cause visible regressions in normal browsing.

Pre-merge author checklist

Pre-merge reviewer checklist

  • I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed).
  • I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.

Part of MetaMask-planning#6402 subtask 1 (set-state-in-effect).

CODEOWNERS: @MetaMask/extension-platform leftovers, @MetaMask/metamask-assets
@metamask-ci metamask-ci Bot added the team-extension-platform Extension Platform team label Aug 11, 2026
@metamask-ci

metamask-ci Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

✨ Files requiring CODEOWNER review ✨

💎 @MetaMask/metamask-assets (1 files, +5 -1)
  • 📁 ui/
    • 📁 components/
      • 📁 app/
        • 📁 assets/
          • 📁 nfts/
            • 📁 nft-details/
              • 📄 nft-full-image.tsx +5 -1

@github-actions

Copy link
Copy Markdown
Contributor

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

@metamask-ci

metamask-ci Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor
Builds ready [501f609]
⚡ Performance Benchmarks (Total: 🟢 10 pass · 🟡 13 warn · 🔴 1 fail)

Baseline (latest main): 171ed20 | Date: 7/28/2026 | Pipeline: 31515721831 | Baseline logs

Metricschrome-webpackfirefox-webpack
onboardingImportWallet
[Sentry log · main/release]
🔴 srpButtonToSrpForm(p95) [CI log]🟢 [CI log]

Regressions (🔴 1 failure)

Interaction Benchmarks · Samples: 5
Benchmarkchrome-webpackfirefox-webpack
loadNewAccount
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
🟡 load_new_account
confirmTx
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
bridgeUserActions
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]

📈 Results compared to the previous 5 runs on main

  • loadNewAccount/fcp: -18%
  • loadNewAccount/lcp: +615%
  • confirmTx/longTaskCount: -67%
  • confirmTx/longTaskTotalDuration: -66%
  • confirmTx/tbt: -65%
  • confirmTx/inp: -17%
  • confirmTx/fcp: -15%
  • confirmTx/lcp: -11%
  • bridgeUserActions/bridge_load_asset_picker: +19%
  • bridgeUserActions/longTaskCount: -100%
  • bridgeUserActions/longTaskTotalDuration: -100%
  • bridgeUserActions/longTaskMaxDuration: -100%
  • bridgeUserActions/tbt: -100%
  • bridgeUserActions/inp: -15%
  • bridgeUserActions/lcp: -16%
  • loadNewAccount/load_new_account: +22%
  • loadNewAccount/total: +22%
  • loadNewAccount/inp: -24%
  • loadNewAccount/lcp: +1164%
  • confirmTx/confirm_tx: +11%
  • confirmTx/longTaskCount: -100%
  • confirmTx/longTaskTotalDuration: -100%
  • confirmTx/longTaskMaxDuration: -100%
  • confirmTx/tbt: -100%
  • confirmTx/total: +11%
  • confirmTx/inp: -24%
  • confirmTx/fcp: -40%
  • confirmTx/lcp: +1250%
  • bridgeUserActions/bridge_load_page: +188%
  • bridgeUserActions/bridge_load_asset_picker: +111%
  • bridgeUserActions/bridge_search_token: +16%
  • bridgeUserActions/longTaskCount: -100%
  • bridgeUserActions/longTaskTotalDuration: -100%
  • bridgeUserActions/longTaskMaxDuration: -100%
  • bridgeUserActions/tbt: -100%
  • bridgeUserActions/total: +38%
  • bridgeUserActions/inp: -23%
  • bridgeUserActions/lcp: +1193%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 loadNewAccount/FCP: p75 1.9s
  • 🟡 bridgeUserActions/FCP: p75 1.9s
Startup Benchmarks · Samples: 100
Benchmarkchrome-webpackfirefox-webpack
startupStandardHome
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
🟡 loadScripts
startupPowerUserHome
[Sentry log · main/release]
🟡 [CI log]

📈 Results compared to the previous 5 runs on main

  • startupStandardHome/backgroundConnect: +15%
  • startupStandardHome/firstReactRender: -99%
  • startupStandardHome/numNetworkReqs: -14%
  • startupStandardHome/lcp: +11%
  • startupStandardHome/domInteractive: -11%
  • startupStandardHome/backgroundConnect: +15%
  • startupStandardHome/firstReactRender: -98%
  • startupStandardHome/setupStore: +13%
  • startupStandardHome/numNetworkReqs: -13%
  • startupPowerUserHome/load: +20%
  • startupPowerUserHome/domContentLoaded: +20%
  • startupPowerUserHome/domInteractive: +48%
  • startupPowerUserHome/backgroundConnect: +19%
  • startupPowerUserHome/firstReactRender: -99%
  • startupPowerUserHome/initialActions: +11%
  • startupPowerUserHome/loadScripts: +19%
  • startupPowerUserHome/setupStore: +289%
  • startupPowerUserHome/fcp: +47%
  • startupPowerUserHome/lcp: +18%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 startupPowerUserHome/LCP: p75 3.4s
User Journey Benchmarks · Samples: 5 · mock API 🔴 1
Benchmarkchrome-webpackfirefox-webpack
onboardingImportWallet
[Sentry log · main/release]
🔴 [CI log]
🔴 total
🟢 [CI log]
onboardingNewWallet
[Sentry log · main/release]
🟢 [CI log]
🔴 total
🟡 [CI log]
🟡 total
assetDetails
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
solanaAssetDetails
[Sentry log · main/release]
🟡 [CI log]🟡 [CI log]
🟡 assetClickToPriceChart
importSrpHome
[Sentry log · main/release]
🟡 [CI log]🟡 [CI log]
sendTransactions
[Sentry log · main/release]
🟡 [CI log]🟡 [CI log]
swap
[Sentry log · main/release]
🟡 [CI log]🟡 [CI log]

📈 Results compared to the previous 5 runs on main

  • onboardingImportWallet/srpButtonToSrpForm: +13%
  • onboardingImportWallet/metricsToWalletReadyScreen: -10%
  • onboardingImportWallet/doneButtonToHomeScreen: -92%
  • onboardingImportWallet/openAccountMenuToAccountListLoaded: -42%
  • onboardingImportWallet/longTaskCount: -86%
  • onboardingImportWallet/longTaskTotalDuration: -95%
  • onboardingImportWallet/longTaskMaxDuration: -91%
  • onboardingImportWallet/tbt: -99%
  • onboardingImportWallet/total: -79%
  • onboardingNewWallet/srpButtonToPwForm: +11%
  • onboardingNewWallet/longTaskCount: -38%
  • onboardingNewWallet/longTaskTotalDuration: -53%
  • onboardingNewWallet/longTaskMaxDuration: -36%
  • onboardingNewWallet/tbt: -80%
  • solanaAssetDetails/assetClickToPriceChart: +271%
  • solanaAssetDetails/longTaskCount: -100%
  • solanaAssetDetails/longTaskTotalDuration: -100%
  • solanaAssetDetails/longTaskMaxDuration: -100%
  • solanaAssetDetails/tbt: -100%
  • solanaAssetDetails/total: +271%
  • solanaAssetDetails/inp: +11%
  • solanaAssetDetails/fcp: +23%
  • importSrpHome/longTaskCount: -37%
  • importSrpHome/longTaskTotalDuration: -40%
  • importSrpHome/longTaskMaxDuration: -30%
  • importSrpHome/tbt: -45%
  • importSrpHome/inp: -40%
  • importSrpHome/cls: +484%
  • sendTransactions/openSendPageFromHome: +30%
  • sendTransactions/selectTokenToSendFormLoaded: +75%
  • sendTransactions/reviewTransactionToConfirmationPage: -97%
  • sendTransactions/longTaskCount: -100%
  • sendTransactions/longTaskTotalDuration: -100%
  • sendTransactions/longTaskMaxDuration: -100%
  • sendTransactions/tbt: -100%
  • sendTransactions/total: -93%
  • sendTransactions/inp: -22%
  • sendTransactions/fcp: +19%
  • sendTransactions/lcp: -57%
  • sendTransactions/cls: +171%
  • swap/openSwapPageFromHome: -12%
  • swap/fetchAndDisplaySwapQuotes: +103%
  • swap/longTaskCount: +33%
  • swap/tbt: -79%
  • swap/total: +118%
  • swap/lcp: -71%
  • swap/cls: -92%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 solanaAssetDetails/FCP: p75 1.9s
  • 🟡 importSrpHome/FCP: p75 1.8s
  • 🟡 sendTransactions/FCP: p75 2.0s
  • 🟡 swap/FCP: p75 1.9s
  • 🟡 solanaAssetDetails/FCP: p75 2.0s
  • 🟡 importSrpHome/FCP: p75 1.9s
  • 🟡 sendTransactions/FCP: p75 2.1s
  • 🟡 sendTransactions/LCP: p75 2.6s
  • 🟡 swap/FCP: p75 2.1s
Dapp Page Load Benchmarks · Samples: 100
Benchmarkchrome-webpack
dappPageLoad
[Sentry log · main/release]
🟢 [CI log]

📈 Results compared to the previous 5 runs on main

  • dappPageLoad/pageLoadTime: -57%
  • dappPageLoad/firstPaint: -41%
  • dappPageLoad/firstContentfulPaint: -41%
Bundle size diffs
  • background: 105 Bytes (0%)
  • ui: -196 Bytes (0%)
  • common: 0 Bytes (0%)
  • other: 0 Bytes (0%)
  • contentScripts: 0 Bytes (0%)
  • zip: -30 Bytes (0%)

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR is a broad UI/hooks cleanup aimed at eliminating react-hooks/set-state-in-effect warnings by refactoring prop→state synchronization, derived values, and one-time tracking logic across platform UI pages, shared hooks, and a few components (including NFT full-image fade-in).

Changes:

  • Refactors many effects that synchronously updated state into derived render-time values, refs, and/or deferred work (e.g., queueMicrotask, requestAnimationFrame).
  • Updates several pages/components to de-dupe “consume once” behaviors (toasts, route transitions, QR flows, etc.) without effect-driven state syncing.
  • Improves some derived-state patterns (e.g., memoizing checksum validity in SRP import) and adjusts a few UI timing behaviors (spin delay, NFT fade-in).

Reviewed changes

Copilot reviewed 32 out of 32 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
ui/pages/token-management/token-management.tsx Refactors route-toast consumption logic to avoid effect-driven state syncing.
ui/pages/routes/global-menu-route-transition.tsx Reworks transition-direction updates tied to route changes.
ui/pages/networks/networks-page.tsx Changes edit-complete toast triggering and edited-network reset behavior.
ui/pages/networks/chainlist-network-picker.tsx Resets pagination on search changes without an effect.
ui/pages/keychains/reveal-seed.tsx Adjusts phishing scan reset logic and switches SRP view tracking to a ref.
ui/pages/defi/hooks/useDeFiPositionsV2.ts Resets failure state when account group changes without effect-driven syncing.
ui/pages/custom-token-import/custom-token-import.tsx Updates network/form reset behavior keyed off selected network changes.
ui/pages/contacts/components/add-contact-form.tsx Refactors QR-driven address fill/validation and QR clearing logic.
ui/pages/batch-sell/pages/review/batch-sell-review-page.tsx Closes modal when quote refresh expires without effect-based syncing.
ui/hooks/useTokenTracker.js Changes tracker initialization/loading reset behavior and defers tracker construction.
ui/hooks/useTokenSecurityData.ts Refactors request keying and defers fetch to avoid sync state updates in effects.
ui/hooks/useTheme.ts Removes derived theme state and returns resolved theme directly.
ui/hooks/useSpinDelay.ts Reworks spinner delay/min-duration state machine and timeout management.
ui/hooks/useShouldShowSpeedUp.js Refactors speed-up enabling/timer scheduling logic.
ui/hooks/useMultichainAccountsIntroModal.ts Replaces effect-based modal visibility syncing with derived conditions + override.
ui/hooks/useIntersectionObserver.ts Alters ref reset behavior and intersection state reset handling.
ui/hooks/useEqualityCheck.js Changes equality memoization logic used to stabilize references.
ui/hooks/useDebouncedValue.ts Returns raw value immediately when delay is disabled.
ui/hooks/useCarouselManagement/useCarouselManagement.ts Refactors download eligibility readiness initialization/reset behavior.
ui/components/ui/tabs/tabs.tsx Updates active tab index syncing behavior to avoid effect-based updates.
ui/components/ui/metafox-logo/horizontal-logo.js Removes theme state/effect and derives theme directly.
ui/components/ui/button-group/button-group.component.js Updates active button index syncing without effect-based updates.
ui/components/app/wallet-overview/coin-overview.tsx Refactors zero-fiat-balance delay reset logic.
ui/components/app/toast-master/toast-master.js Switches view-tracking state to a ref for storage error toast.
ui/components/app/srp-input-import/srp-input-import.tsx Memoizes checksum validity instead of storing it in state.
ui/components/app/qr-hardware-popover/qr-hardware-sign-request/qr-hardware-sign-request/qr-hardware-sign-request.tsx Resets QR signing flow status on request changes without an effect.
ui/components/app/permission-page-container/permission-page-container.component.js Refactors Snaps privacy warning handling logic/state.
ui/components/app/name/name-details/name-details.tsx Refactors saved-name/source syncing and tracks open metric via ref.
ui/components/app/currency-input/currency-input.js Moves upstream-value alignment logic and conversion-dependent syncing out of effects.
ui/components/app/confirm/info/row/expandable-row.tsx Changes expandable height measurement approach to avoid forced re-render effect.
ui/components/app/assets/nfts/nft-details/nft-full-image.tsx Defers visibility change via rAF to preserve fade-in behavior.
ui/components/app/alert-system/multiple-alert-modal/multiple-alert-modal.tsx Refactors alert-key reconciliation logic and pending/current selection handling.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines 18 to +22
const [computedValue, setComputedValue] = useState(value);

useLayoutEffect(() => {
if (!equalityFn(value, computedValue)) {
setComputedValue(value);
}
}, [value, equalityFn, computedValue]);
if (!equalityFn(value, computedValue)) {
setComputedValue(value);
}
Comment on lines +88 to 92
const [prevRef, setPrevRef] = useState(ref);
if (ref !== prevRef) {
setPrevRef(ref);
if (!ref && state.entry?.target) {
setState({ isIntersecting: initialIsIntersecting, entry: undefined });
Comment on lines 152 to +155
if (!addresses.includes(scannedAddress)) {
setInput(scannedAddress);
validate(scannedAddress);
}
Comment on lines +147 to +151
if (
hexValue !== prevHexValue ||
asset?.address !== prevAssetAddress ||
isTokenPrimary !== prevIsTokenPrimary ||
assetDecimals !== prevAssetDecimals ||
Comment on lines +29 to 33
const setContentRef = useCallback((node: HTMLSpanElement | null) => {
if (node) {
setContentHeight(node.scrollHeight);
}
}, []);
Comment on lines +204 to +208
if (
alertKey !== prevAlertKey ||
alertsKeyFingerprint !== prevAlertsKeyFingerprint ||
navigableAlertsKeyFingerprint !== prevNavigableAlertsKeyFingerprint
) {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants