In one benchmark of a 4,000-row React table, adding memo() alone barely changed the slowest measured filtering render: 166 ms without memoization versus 153 ms with it. A version that stabilized props with useCallback and useMemo measured 47 ms, while virtualization measured 3.6 ms. The apparent winner, a 0.4 ms children bailout, did not filter at all. These are results from one repository’s test setup—not performance guarantees for other tables or devices.
What the five approaches measured
The public react-rerender-benchmark repository tests a 4,000-row table with a filter box. It reports production-build timings on a 2-core Linux VM, using the slowest result from four typed keystrokes and the median across two passes. Each figure below is the longest re-render reported for that variant under this test.
As an Amazon Associate I earn from qualifying purchases.
| Approach | Reported longest re-render | Filtering still worked? | What the result means |
|---|---|---|---|
| Naive, without memoization | 166 ms | Yes | The repository’s baseline. |
memo() only |
153 ms | Yes | Just 13 ms below baseline; the repository describes the difference as within run-to-run noise. |
memo with useCallback and useMemo |
47 ms | Yes | The repository’s stabilized memoization version. |
| Children bailout | 0.4 ms | No | The query never reached the table, so this did not perform the filtering task. |
| Virtualized rows | 3.6 ms | Yes | Visible rows were rendered using @tanstack/react-virtual. |
The repository reports 10–15% absolute variation between runs, while ratios stayed stable across six runs. In one of those runs, memoization alone was slower than the baseline. Its author attributes the small memo-only change to a newly created onSelect function: that new function invalidated the shallow prop comparison. The figures therefore illustrate what happened in this workload; they do not predict timings for a different app.
Why memoization alone did little
React’s memo reference explains that a memoized component may skip rendering when its props have not changed. It is an optimization, not a guarantee. By default, React compares each prop shallowly, so a newly created function, object, or array is considered changed even if it does the same job or contains the same values.
#1 Best Overall
That is the problem the benchmark demonstrates: memoizing a row or table does not help if a parent hands it a new callback on every render. Stabilizing that callback with useCallback, and stabilizing needed values where appropriate with useMemo, can let a useful memo boundary skip work. The point is not to add hooks everywhere; it is to check whether changing prop identity is preventing a measured optimization from working.
What the fast children bailout actually skipped
The children bailout’s 0.4 ms is not a successful filtering result. Because the query did not reach the table, the implementation avoided the work by removing the requested behavior. It is an example of a benchmark result that looks impressive but does not compare equivalent outcomes.
A bailout can still be useful when a state change genuinely does not need to reach an expensive subtree—for example, a drawer, hover state, or collapsed sidebar, as the repository notes. It is not a filter optimization when filtering is the task.
When virtualization is a better fit
TanStack Virtual describes virtualization as rendering visible items together with an overscan buffer, rather than putting every row in the DOM. In the repository’s benchmark, this approach preserved filtering and reported a 3.6 ms longest re-render.
Rank #3
Virtualization addresses the cost of rendering and maintaining a large set of DOM elements. It does not reduce the amount of data already loaded into the browser, and it is not a replacement for server-side filtering, sorting, or pagination. If the dataset is too large to load client-side, server-side data operations address a different constraint. For a small table, ordinary rendering is simpler and is usually preferable.
Account for the user-facing trade-offs
Virtual rows can affect how people navigate and use the document. The benchmark repository cautions that off-screen rows are not found by browser Ctrl+F, and keyboard and screen-reader navigation require deliberate attention. Printing and exporting may also need a separate non-virtualized render. These are the repository author’s caveats, not a universal accessibility audit; test the actual table and its workflows.
Rank #4
How to decide what to optimize
- Profile the slow interaction first. React’s
<Profiler>reference documentsactualDuration, the time spent rendering a profiled subtree for an update, andbaseDuration, an estimate of its render cost without optimizations. Profiling adds overhead. The normal production build disables profiling unless a profiling build is enabled. - Use memoization at a useful boundary. Check whether a costly component repeatedly renders with the same props. If new objects, arrays, or functions make props appear different, stabilize only the values needed for the intended boundary, then measure whether it helps.
- Use
useMemofor a measured reason. React’suseMemoreference says it reuses a calculation result while dependencies are unchanged. It can also stabilize a value when that enables a useful memo boundary. React cautions against relying on it for correctness or applying it indiscriminately. - Consider virtualization when rendered row or column counts are genuinely large. It can reduce DOM work, but weigh that against navigation, find, print, and export requirements—and remember that client-side virtualization still requires loading the data in the browser.
- Measure under production-like conditions. The benchmark warns that development builds are slower and Strict Mode double-renders. React’s
useMemoguidance likewise cautions that development measurements are less accurate and recommends production testing on hardware like the user’s. Compare implementations that complete the same interaction.
What this benchmark can—and cannot—tell you
For this repository’s 4,000-row table and test conditions, memoization alone did little, stabilized memoization and virtualization reduced the reported filtering time, and the fastest figure came from skipping filtering. The repository is the primary source for its own workload and results; the cited React and TanStack documentation explains the relevant APIs and concepts. The figures should not be generalized to other applications, devices, or datasets.
Recommended Free Tools
Quick Recap
Best Value
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.




