Memoize selectCustomNetworkConfigurationsByCaipChainId filter result

Open Beginner friendly
#31,348 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
84/100
Issue type
Refactor
Clarity
Clearly specified
Activity status
Quiet
Tech stack
typescript

Research direction

Start with app/selectors/networkController.ts:274 and inspect how selectCustomNetworkConfigurationsByCaipChainId derives its result. Then read app/selectors/networkController.test.ts:177 and add coverage for referential stability across equal-content states. Done means the selector preserves the array reference when contents are unchanged and the selector tests pass.

Written by the indexing model from the issue text.

Description

area-performance Sev3 size-XS ta-triaged team-mobile-ux team-networks

Performance audit finding · Severity: Medium · Effort: Easy · Fix risk: Simple · Test safety net: Partial
Owner: @MetaMask/mobile-core-ux (suggested)
File: app/selectors/networkController.ts:274

What is this about?

selectCustomNetworkConfigurationsByCaipChainId is a plain createSelector whose result function returns Object.values(...).filter(...), building a new array every recompute. Its input selectNetworkConfigurationsByCaipChainId is a plain createSelector that builds a fresh object (via getNetworkConfigurationsByCaipChainId spreads) whenever either network slice changes, so this selector reruns and yields a new array on any network-slice mutation.

Why it matters

Custom network lists feed network management/picker UI. A new array reference forces consumers to re-render even when the custom networks are unchanged.

Scenario

N/A — see Technical Details.

Design

N/A — internal performance change; no UI/design impact.

Technical Details

Evidence

app/selectors/networkController.ts:274

export const selectCustomNetworkConfigurationsByCaipChainId = createSelector(
  selectNetworkConfigurationsByCaipChainId,
  (networkConfigurationsByChainId) =>
    Object.values(networkConfigurationsByChainId).filter(
      (networkConfiguration) =>
        (networkConfiguration.chainId.startsWith('0x') &&
          !POPULAR_NETWORK_CHAIN_IDS.has(networkConfiguration.chainId as Hex)) ||
        NON_EVM_TESTNET_IDS.includes(networkConfiguration.caipChainId),
    ),
);

Fix

Switch to createDeepEqualSelector so the filtered array is referentially stable when contents are unchanged.

Threat Modeling Framework

N/A — performance-only change; behavior is preserved, no new data flow / trust boundary / attack surface.

Acceptance Criteria
  • app/selectors/networkController.test.ts:177 asserts values but not referential stability. Add a test asserting toBe across two equal-content states. Profiler: confirm network-management consumers stop re-rendering on unrelated network-state changes.
References
  • File: app/selectors/networkController.ts:274
  • Source: MetaMask Mobile performance audit — finding selector-custom-network-configs-by-caip
  • Owner (CODEOWNERS / best-effort): @MetaMask/mobile-core-ux (suggested)
  • Status: UNVALIDATED
Dominant language
TypeScript
Stars
3k
Forks
1.7k
Avg merge
1d 14h
Merged PRs (30d)
653

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from MetaMask/metamask-mobile

All issues in MetaMask/metamask-mobile

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.