iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
To improve React performance, first reproduce a specific slow interaction and profile the work it triggers. Fix unnecessary state updates, Effects, or rendering before adding memoization; then use React Compiler or targeted memoization only when measurements identify repeated work. Reproduce the interaction and profile it again to check the result.
Start with a specific slowdown
Choose one interaction you can reproduce: typing into a sluggish filter, updating a large list, or navigating to a route that feels delayed. Note what you do and what feels slow. That gives you a consistent case to inspect before and after a change.
Do not assume every re-render is a problem. React’s guidance says memoization is usually unnecessary for coarse interactions that do not feel slow. Optimize the work behind a perceptible slowdown, rather than trying to prevent rendering everywhere.
Profile the interaction that feels slow
Use the React Developer Tools Profiler tab to record the relevant interaction and inspect which components rendered and where time was spent. This interactive view is a practical starting point for locating components that may benefit from memoization.
#1 Best Overall
For repeatable measurements of a chosen subtree, wrap it with React’s <Profiler> API:
<Profiler id="SearchResults" onRender={onRender}>
<SearchResults items={items} query={query} />
</Profiler>
The callback includes actualDuration, the time spent rendering the subtree for the current update, and baseDuration, an estimate of how long rendering the subtree would take without optimizations. These help compare render work in that subtree; they are not universal measures of how fast the app feels to a user. See React’s Profiler API reference for callback details.
Profiling adds overhead. The standard production build disables the Profiler; production profiling requires a special profiling-enabled build. Development traces can also differ from production behavior. For more representative timing, use a production build and test on a device like your users’ devices. CPU throttling can help account for a faster development machine. React’s useMemo guidance also recommends profiling before optimizing.
Remove avoidable update work first
Before introducing caches, inspect why the interaction causes work. React’s performance guidance highlights Effect-driven state updates and render bugs as problems to address directly, rather than mask with memoization.
Rank #3
- Look for Effect-driven update chains. An Effect that updates state can trigger another render and more work. Check whether the state can instead be derived during rendering or updated directly by the interaction.
- Keep transient state local. State used only by one part of the interface need not be lifted higher, where its updates may involve more of the component tree.
- Keep rendering pure. A render should not produce side effects or depend on mutations that make repeated rendering behave differently.
- Pass JSX through wrappers when appropriate. If a wrapper’s own state changes but its content does not need to, passing that content as children can avoid involving descendants in the wrapper’s update.
These changes target unnecessary work at its source. React’s documentation discusses them in its useMemo guidance and memo guidance.
Choose memoization based on the repeated work
Once profiling points to repeated work, match the tool to the cause. React describes memoization as an optimization, not a requirement for correct behavior. A cache helps only when its dependencies or props stay unchanged often enough for React to skip work.
Rank #4
| Approach | What it can skip or stabilize | When it may help | What can defeat it |
|---|---|---|---|
useMemo |
Caches a calculation result while its dependencies are unchanged. | A calculation is noticeably slow; a stable value is passed to a memoized child; or a value is needed as another Hook’s dependency. | A dependency changes on every render, such as a newly created object. |
useCallback |
Caches a function reference while its dependencies are unchanged. | A callback is passed to a memoized child and stable identity can let that child skip rendering. | A dependency changes on every render, or the receiving component is not able to skip work based on the stable reference. |
memo |
Lets a component skip rendering when its props are unchanged. | A component often receives the same props and its render work is expensive. | A prop is a newly created object or function each time, so it is not unchanged by reference. |
React’s references explain the details and caveats for useMemo, useCallback, and memo. If the measured issue is a genuinely expensive calculation, memoizing the result may address it; if it is repeated child rendering, stable props and a memoized component may be relevant. Do not add all three automatically.
Free tools Windows power users keep installed
One-click scans. No signup required.
React’s documentation states, “useMemo is a performance optimization, not a semantic guarantee,” and, “You should only rely on memo as a performance optimization.” Your component must remain correct if React recalculates a memoized value or renders a memoized component. Avoid using referential equality as a correctness condition.
Best Value
Account for React Compiler
React Compiler is a build-time tool that analyzes code and can automatically memoize values and components. React’s compiler introduction recommends relying on the compiler for memoization in most new code, while manual Hooks remain useful when precise control is needed.
If a project uses React Compiler, do not reflexively add manual useMemo, useCallback, or memo to every component. Keep existing manual memoization in place unless there is a reason to change it; removing it can alter compiler output, so test carefully. Compiler optimization does not make correctness assumptions based on referential equality safe. React’s compiler debugging guidance describes how to investigate code that relies on such assumptions.
Compare the result and check correctness
- Repeat the same interaction you profiled before the change, using the same data and steps where possible.
- Record the relevant component renders or Profiler timings again, in the same environment and with the same instrumentation.
- Check that the interaction still produces the right output, including when dependencies or props change.
- Keep the change only if it addresses the observed work without breaking behavior. If the profile does not improve, revisit the cause instead of adding more memoization.
React’s documentation does not establish a fixed performance gain for a compiler setting or memoization change. Results depend on the application’s code, workload, device, and measurement context, so report only what measurements for the application show.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

