Find the React Re-Render That Makes Typing Lag
Typing lag is often a render problem hiding behind a small input. One state update at the top of a page can ask an expensive table, chart, and sidebar to render on every keystroke. The values may look identical, but a new object or callback has a new identity.
Do not start by wrapping everything in memo. Profile the interaction first.
Record the bad interaction
Use the React Profiler in a production-like build. Record one repeatable action, such as typing ten characters into the search field. Mark:
- which component owns the input state;
- which components rendered for each character;
- render duration;
- the first expensive component that did not need the new value;
- which props changed by identity.
Development Strict Mode can intentionally render more than once, so confirm the performance result in the build users run.
Read identity, not appearance
These values are new on every parent render:
<Results filters={{status: 'open'}} onSelect={(id) => setSelected(id)} />
Even when the object contains the same text, React sees a different reference. Hoist stable values,
use useMemo or useCallback when a measured boundary needs them, or change the child API to pass
primitives.
Memoization has a cost and can create stale-closure bugs. It is useful when the child is expensive, its inputs are stable, and the profiler proves the skipped work matters.
Move state closer to the change
If only the search box needs the raw keystrokes, keep that state near the box. Pass a committed or debounced query to the expensive results tree. Do not make the entire dashboard subscribe to an input value it never reads.
Also inspect context providers. One new provider value can re-render every consumer. Split contexts by update frequency or memoize the provider value after measuring.
Prove the fix
Record the same ten-character trace. Compare total commit time, expensive render count, and input delay. Then run behaviour tests for selection, filters, and stale callbacks. A faster trace that shows old data is not a win.
Claude can inspect the component tree and suggest likely identity changes. The profiler decides which one is real.
Run the starter locally
npm test
npm run validate
npm run sample
The pack validates a fictional profiler report and returns a reviewable optimization plan. It does not edit React code or apply memoization automatically.