Memoize QRHardwareContext provider value and stabilize inline setters
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 72/100
- Issue type
- Refactor
- Clarity
- Clearly specified
- Activity status
- Quiet
- Tech stack
- react, typescript
Research direction
Start with app/components/Views/confirmations/context/qr-hardware-context/qr-hardware-context.tsx at the provider around line 85, then read qr-hardware-context.test.tsx. Verify the provider callbacks and value are stable across unrelated updates without changing behavior. Run the specified Jest test and profile the QR-signing flow to confirm consumers avoid unnecessary re-renders.
Written by the indexing model from the issue text.
Description
Performance audit finding · Severity: Medium · Effort: Easy · Fix risk: Simple · Test safety net: Partial
Owner:@MetaMask/confirmations
File:app/components/Views/confirmations/context/qr-hardware-context/qr-hardware-context.tsx:85
What is this about?
QRHardwareContextProvider passes an inline object literal to the provider, and two of its fields are inline arrow functions created fresh every render (setRequestCompleted: () => setRequestCompleted(true) and setSigningConfirmed: () => setSigningConfirmed(true)). Both the object and those function refs change on every render.
Why it matters
The provider re-renders whenever useQRHardwareAwareness() (a Redux selector on state.qrKeyringScanner) emits, plus on each local state change (scannerVisible, signingConfirmed, isRequestCompleted). With 6 consumer files in the QR-signing confirmation flow, every such update re-renders all consumers because the context value identity is unstable.
Scenario
N/A — see Technical Details.
Design
N/A — internal performance change; no UI/design impact.
Technical Details
Evidence
app/components/Views/confirmations/context/qr-hardware-context/qr-hardware-context.tsx:85
<QRHardwareContext.Provider
value={{
pendingScanRequest,
cameraError,
cancelQRScanRequestIfPresent,
isSigningQRObject,
needsCameraPermission: isSigningQRObject && !hasCameraPermission,
scannerVisible,
setRequestCompleted: () => setRequestCompleted(true),
setScannerVisible,
setSigningConfirmed: () => setSigningConfirmed(true),
signingConfirmed,
}}
>
cancelQRScanRequestIfPresent is already useCallback-stabilized; the two inline setters and the object wrapper are not.
Fix
Promote the inline setters to useCallback-wrapped functions and wrap the value in useMemo:
const markRequestCompleted = useCallback(() => setRequestCompleted(true), []);
const confirmSigning = useCallback(() => setSigningConfirmed(true), []);
const value = useMemo(
() => ({ pendingScanRequest, cameraError, cancelQRScanRequestIfPresent, isSigningQRObject,
needsCameraPermission: isSigningQRObject && !hasCameraPermission, scannerVisible,
setRequestCompleted: markRequestCompleted, setScannerVisible,
setSigningConfirmed: confirmSigning, signingConfirmed }),
[pendingScanRequest, cameraError, cancelQRScanRequestIfPresent, isSigningQRObject,
hasCameraPermission, scannerVisible, markRequestCompleted, confirmSigning, signingConfirmed],
);
Threat Modeling Framework
N/A — performance-only change; behavior is preserved, no new data flow / trust boundary / attack surface.
Acceptance Criteria
-
- Run
yarn jest app/components/Views/confirmations/context/qr-hardware-context/qr-hardware-context.test.tsx.
- Run
- Profile the QR-signing flow and confirm consumers don't re-render on unrelated selector ticks.
References
- File:
app/components/Views/confirmations/context/qr-hardware-context/qr-hardware-context.tsx:85 - Source: MetaMask Mobile performance audit — finding
context-qr-hardware-inline-value - Owner (CODEOWNERS / best-effort): @MetaMask/confirmations
- Status: UNVALIDATED
- Dominant language
- TypeScript
- Stars
- 3k
- Forks
- 1.7k
- Avg merge
- 1d 14h
- Merged PRs (30d)
- 653
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from MetaMask/metamask-mobile
-
client-controller-update ta-bot-triage team-money-movement
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
MetaMask/metamask-mobile#36594 ·
-
client-controller-update ta-triaged team-core-platform
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
MetaMask/metamask-mobile#36424 · 1 comment ·
-
client-controller-update ta-triaged team-assets
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
MetaMask/metamask-mobile#36357 · 1 comment ·
-
client-controller-update ta-triaged team-confirmations
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
MetaMask/metamask-mobile#36346 · 1 comment ·
-
client-controller-update ta-triaged team-money-movement
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
MetaMask/metamask-mobile#36345 · 1 comment ·
All issues in MetaMask/metamask-mobile
Similar issues
-
calcite-components needs triage refactor
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
Esri/calcite-design-system#15203 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 91/100
-
community first-timers-only good first issue hacktoberfest help wanted low hanging fruit up-for-grabs
Difficulty 1/5 Under an hour Newbie friendliness 95/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Automattic/studio#4908 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 90/100