UserCard - same value: useruseMemo in ProfileScreen
WhyRN watches every render and reports only the wasted ones that cost frames - with the prop or context to fix and the
component to fix it in. Real changes and cheap renders stay quiet. Wrap your app once. Dev builds only.
npm i -D whyrn.dev
§1
Press a button. Only waste flashes.
A small React Native screen, simulated. A real state change stays quiet; renders that changed nothing flash, and Metro says what to fix.
Profile tick 0
Countercount 0
UserCardAlice
MemoBoxReact.memo · stable props
ThemeLabeltheme light
renders / 5 s
1
2
4
6
8+
metro ▸ waiting for an avoidable re-render…
§2
What gets flagged, and the fix.
A render is flagged when nothing the component depends on really changed and the waste adds up to a frame (16 ms) per second. The summary names the parent where the unstable value is created.
cause
metro says
fix
object
prop "user": new object with the same content - useMemo in Screen
An object, array or JSX literal is rebuilt on every render of the parent. useMemo it, or hoist it out of the component.
function
prop "onPress": new function every render - useCallback in Counter
An inline handler. useCallback in the parent.
memo
props are equal - wrap FlexChild in React.memo
Nothing changed for this component; it only followed its parent. React.memo skips it.
context
ThemeContext got a new value with the same content - useMemo the Provider value
The provider passes a fresh value object, so every consumer renders.
store
Store selector returned a new object with the same content
A Zustand / Redux selector builds a new object. Select primitives, or use a shallow-equal selector.
quiet
state[0] changed: 14 → 15
A real change - or a wasted render too cheap to matter. Not reported by default; report="avoidable" or "all" shows them.
§3
Setup is one wrapper.
No init call, no Babel plugin, no native module. Bare apps, Expo Go, dev clients; old and new architecture.
⚠️ WhyRN: 9 avoidable re-renders
UserCard ×3 · rendered by Screen
prop "user": new object with the
same content - useMemo in Screen
Button ×6 · rendered by Counter
prop "onPress": new function every
render - useCallback in Counter
The package ships whyrn-debug, an Agent Skill for Claude Code and Codex: measure, fix the cause the log names, measure
again - instead of memoizing everything on a hunch.
# Claude Code
/whyrn-debug The product list stutters
while scrolling. Find out why and fix it.
# Codex
$whyrn-debug Same task.
03 · it reads the log
779 re-renders across 11 components
302 Button (rendered by Screen)
prop "onPress": new function
every render - useCallback
66 ThemeLabel
ThemeContext got a new value
with the same content