In React, an extra re-render is not automatically a performance bug. How do you judge whether a particular re-render is costing anything, and which ones are worth eliminating?
answer
- work times frequency, not count
- render is not a DOM write
- frame budget as the yardstick
- wide, expensive, frequent, or consequential
- cheap render can still refire an effect
basics
~20 sA re-render costs what it does: the size of the subtree it triggers, heavy computation in the render bodies, DOM changes the diff commits, and how often it repeats. Cheap renders at click rate are free; wide subtrees at keystroke rate are not.
solid answer
~50 sI judge it by work times frequency, not by the render count on its own. The work is the component functions that run in the subtree, anything expensive inside those bodies, the reconciliation of the returned elements, and the DOM mutations the diff actually produces — a render that changes nothing commits nothing. The frequency is what turns a harmless render into a problem: half a millisecond on a button click is invisible, the same half millisecond fired per keystroke, per scroll event or per animation frame is not. So I compare a commit's duration against the frame budget of roughly 16 ms for interactive updates, and I chase the renders that are wide, expensive or high-frequency. There is one non-obvious cost worth calling out: a cheap render that changes the identity of a value in an effect's dependency array re-runs that effect, which can mean a refetch. That is a correctness and network cost, not a render cost, and it is often the real reason to care.
go deeper
Know that a render means React called your function and compared output, and that it only changes the DOM where the comparison found a difference — so extra renders are not automatically expensive.
Break the cost down: subtree size, work inside the render body, DOM changes actually committed, and how often the update fires. Be able to say why the frequency term dominates for typing and scrolling.
Argue with numbers. Measure commit duration against the frame budget on representative hardware, and identify the renders that are wide, expensive, frequent or that re-trigger effects and requests.
Set the bar for the team: define what counts as a performance defect in measurable terms, so effort goes to interactions that miss frames rather than to render counts that offend the eye but cost nothing.
## Why the render count alone tells you nothing Developers see a component render forty times and assume forty problems. But React's render step is a function call producing plain objects; it is not a DOM write and it is not a repaint. For a small leaf component the entire cost is a function call, a handful of object allocations and a shallow comparison during reconciliation — comfortably under a tenth of a millisecond. Forty of those is still nothing. The question worth asking is never "did it render?" but "what did that render do, and how often does it happen?" ## The four things a render can actually cost **Subtree size.** Rendering a component means rendering everything beneath it that does not bail out. A render at the root of a tree with two thousand nodes is a fundamentally different event from a render of a leaf, even when both bodies are trivial. **Work inside the render body.** Sorting ten thousand rows, formatting dates per cell, building a large derived object, running a heavy layout calculation — this is real CPU on the main thread every single time the component renders, and it dwarfs React's own overhead. **Committed DOM changes.** If the diff finds differences, React mutates the DOM, and the browser then does style, layout and paint work on those nodes. A render whose output is identical commits nothing and costs the browser nothing. This is precisely why a re-render is not the same as "the page redrew". **Frequency.** The multiplier. Renders triggered by clicks and navigations happen a few times a minute; renders triggered by typing, scrolling, pointer movement, resize observers or animation frames can happen dozens of times a second. The same per-render cost lands in completely different places depending on which of those drives it. ## The budget to measure against For updates that must feel immediate, the practical target is the frame budget — roughly 16 ms at 60 Hz for everything the main thread does in that frame, and less than that once the browser's own style and layout work is counted. A commit that measures 0.3 ms is fine even sixty times a second. A commit that measures 40 ms is a visible stall even once, on a click. Anchoring on a number rather than a feeling is what turns this from an opinion into an engineering decision — and remember to take that number from a production build, since development builds are slower and a `<StrictMode>` subtree double-invokes component bodies in development. Hardware matters too. A render that is comfortable on a development laptop can miss frames on a mid-range phone; if that is your audience, measure with CPU throttling rather than on the machine that wrote the code. ## The cost that does not show up in a profile Some renders are cheap in CPU and expensive in consequence. If a render recreates the object or function that sits in an effect's dependency array, React re-runs that effect. If that effect fetches, you have just issued a network request per render — possibly per keystroke. If it subscribes, you have torn down and rebuilt a subscription. If it measures layout, you have forced a synchronous layout. None of that is visible as render time, and all of it is a real reason to eliminate the render or stabilise the value. The mirror image is worth stating too: a render whose only effect is to run a pure function and produce identical elements is genuinely free, no matter how offensive the count looks in a profiler. ## Which ones to actually chase In practice the renders worth eliminating are the ones that are wide (rooted high in the tree), expensive (heavy work in the body), high-frequency (driven by input, scroll or animation), or consequential (they re-trigger effects, requests or subscriptions). Everything else is noise, and eliminating noise has a price of its own: comparison work at runtime, retained references, and code that a future reader has to reason about. "It renders more than it needs to" is not by itself a defect report — the defect report is "this interaction misses frames, and here is the commit that eats the budget".
- Give an example of a re-render that is cheap in CPU but still worth eliminating.One that recreates a value used in an effect's dependency array. The render itself may cost microseconds, but the effect re-runs, and if it fetches you have issued a network request per render. The visible cost is requests, flicker and possible race conditions rather than render time.
- Why is a component's render count, on its own, a poor performance metric?Because it says nothing about the work per render or the rate. A leaf component rendering fifty times per session costs less than one render of a two-thousand-node subtree. The metric that matters is the duration of the commits driving the slow interaction, measured against the frame budget.
- How would you decide that eliminating a re-render is not worth it?When the measured commit is a fraction of the frame budget, the interaction already feels immediate on the slowest device you support, and no effects or requests hang off it. At that point the change buys nothing measurable and adds comparison work and code that has to be maintained and understood.
saying these in an interview costs you the question
- Treats every extra render as a bug regardless of cost
- Says re-rendering means the DOM was rewritten
- Optimises by render count instead of commit duration
- Ignores how often the update is triggered
- Measures only on a fast development machine