Memoization (Performance) Guide
Mantine React Table already uses some memoization techniques to improve performance for you automatically under the hood to improve performance during some events like column resizing. In this guide, we'll go over the basics of what is recommended to be memoized, what you need to keep in mind for performance, and how to tweak advanced memoization settings for your specific use case.
Relevant Table Options
What to Memoize
First of all, when these docs refer to memoization, we are not necessarily talking just about the React
useMemo hook. Using the
useMemo hook is just one way to give an variable a stable reference in React.
useQuery (React Query), storing state in a state management library like Zustand or Redux, or even just defining a variable outside of a component are all ways to give a variable a stable reference.
Give Data a Stable Reference
The only truly required thing that must have a stable reference for both Mantine React Table and TanStack Table is the
data table option. If your
data does not have a stable reference, the table will enter an infinite loop of re-rendering upon any state change.
Failing to give
dataa stable reference can cause an infinite loop of re-renders.
Why does this happen? Is this a bug in MRT or TanStack Table?
No, this is not a bug in either MRT or TanStack Table. This is just fundamentally how React works. TanStack Table is designed to re-render whenever the
data changes. You would probably be equally surprised and upset if MRT only accepted what you passed in as
data on the first render and never updated after a refetch or state change.
I'm still getting an infinite loop of re-renders, but I'm using useMemo!
Sometimes developers will properly memoize their
data, but don't end up passing that memoized
data to the table, and apply some extra transformation or filtering to the
data before passing it to the table. This common mistake will still cause an infinite loop of re-renders.
You will generally have better performance if you properly memoize your
columns array, or give it a stable reference like you would with
data. Not giving
columns a stable reference will not cause an infinite loop of re-renders like
data, but it will still cause the table to re-render more than necessary. The columns
useMemo dependency array does not need to be an empty array. If your column definitions are derived from other state, you should include that state in the dependency array.
Other Options to Memoize
Usually you will not need to memoize any other options besides
data. However, if you have any expensive logic in any of the
render* options, you may benefit from wrapping that logic in a React
useCallback hook. It is not recommended to start off by wrapping all of your
render* options in
useCallback hooks, as this usually does not even provide a noticeable performance improvement. This usually takes some experimentation.
Here's an example for how to render detail panels with a
useCallback optimization. Getting the TypeScript types correct in the
useCallback can be tricky, but here's how you can do it:
All of the other
mantine*Props components could also be memoized with either
useCallback if you have complicated expensive logic in them for some reason in the same way as above.
Mantine React Table already memoizes columns and the entire
<tbody> component during column resizing, and column/row drag and drop events. This actually does make a significant performance improvement, and is why it is possible to have the performance that it does during these events.
If you need to reach into the internals and apply some custom memoization, MRT exposes a limited way to do this. The Table Body, Table Rows, or all Table Cells can be memoized with the
memoMode table option.
Usually you should not ever need to do this, and be aware that this will stop certain features from functioning correctly. For example, if you memoize all table cells, the density toggle feature will not work anymore. If you memoize the entire table body, most features including virtualization will not work anymore. You'll be left with a table that is mostly frozen after first render, but it could improve the overall performance of your web page if you don't need any of these interactive features.
memoModeunless you know what you're doing and have a specific use case for it.
In the future, React may finally release their magical "React Forget" compiler that will make all memoization problems in React disappear, and you won't have to worry about any of this. But until then, the above solutions are the best we have.
View Extra Storybook Examples