MetaMask / MetaMask/metamask-mobile

Memoize TabIconAnimationContext value in HomepageDiscoveryTabs

Open Beginner friendly
#31,289 1 comment 0 reactions 0 assignees View on GitHub
area-performance Sev3 size-XS ta-ai-fixable ta-triaged team-mobile-platform team-mobile-ux
Dominant language
TypeScript
Stars
3k
Forks
1.7k
Avg merge
1d 14h
Merged PRs (30d)
669

Description

> **Performance audit finding** · Severity: **Low** · Effort: Easy · Fix risk: Simple · Test safety net: Uncovered
> Owner: `@MetaMask/mobile-core-ux`
> File: `app/components/Views/Homepage/components/HomepageDiscoveryTabs/HomepageDiscoveryTabs.tsx:343`

### What is this about?

`HomepageDiscoveryTabs` provides `TabIconAnimationContext.Provider value={{ iconCollapseProgress }}` with an inline object literal. `iconCollapseProgress` is a Reanimated `SharedValue` (stable ref), but the wrapping object is re-created every render.

**Why it matters**

`HomepageDiscoveryTabs` re-renders frequently (it is the Homepage tab host: scroll-driven header animation, tab changes, Perps WS toggles). Each re-render hands consumers (`TabsIconTab`) a new context object. The consumer only reads `iconCollapseProgress` inside `useAnimatedStyle` (so the per-frame animation itself stays on the UI thread and is unaffected), but the inline object still forces every `TabsIconTab` to re-render on each parent render. Severity is Low because the SharedValue is stable and the consumer count is small, but it is still avoidable churn on a hot host component.

### Scenario

N/A — see Technical Details.

### Design

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

### Technical Details

**Evidence**

`app/components/Views/Homepage/components/HomepageDiscoveryTabs/HomepageDiscoveryTabs.tsx:343`
```tsx

```
Consumer `app/component-library/components-temp/Tabs/TabsIconTab/TabsIconTab.tsx:45`:
```tsx
const { iconCollapseProgress } = useContext(TabIconAnimationContext);
```

**Fix**

`iconCollapseProgress` is a stable SharedValue ref, so memoize the wrapper once:
```tsx
const tabIconAnimationValue = useMemo(
() => ({ iconCollapseProgress }),
[iconCollapseProgress],
);
...

```

### Threat Modeling Framework

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

### Acceptance Criteria

- - No dedicated test; behavior is identical (same SharedValue).
- Profile the Homepage while scrolling and confirm `TabsIconTab` no longer re-renders on every parent render.

### References

- File: `app/components/Views/Homepage/components/HomepageDiscoveryTabs/HomepageDiscoveryTabs.tsx:343`
- Source: MetaMask Mobile performance audit — finding `context-tabicon-animation-inline-value`
- Owner (CODEOWNERS / best-effort): @MetaMask/mobile-core-ux
- Status: **UNVALIDATED**

Contributor guide

Open the contributing guide

Research direction

Start in app/components/Views/Homepage/components/HomepageDiscoveryTabs/HomepageDiscoveryTabs.tsx at the TabIconAnimationContext.Provider around line 343, then inspect the TabsIconTab consumer in app/component-library/components-temp/Tabs/TabsIconTab/TabsIconTab.tsx. Memoize the provider value without changing the SharedValue, and profile Homepage scrolling to confirm TabsIconTab no longer re-renders on every parent render.

Written by the indexing model from the issue text.

Assessment

Tech stack
react-native, typescript
Domain
frontend, mobile-dev, performance
Issue type
Refactor
Difficulty
1/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.