Add CellMeasurer cache per item
See original GitHub issueHi,
First, I would like to say how much I like react-virtualized, it is a beautiful piece of software and it helped me a lot.
This issue can be related to #341.
Problem
When using <CellMeasurer>
with a <Grid/>
, the current cache strategy is to store/retrieve the row height and the column width. While this is helpful, it leads to pretty complex cache systems if we have the following constraints:
- An item can be inserted/moved/removed anywhere in the list
- An item can be modified (which would modify its dimensions)
Let’s say I have a grid 3 columns by 3 rows.
If I cache per id, I would have to cache a value for each combination. For instance after the first render I would have a row height cache looking like that:
{
Item1Id&Item2Id&Item3Id: 400
Item4Id&Item5Id&Item6Id: 200
Item7Id&Item8Id&Item9Id: 300
}
If I insert a 10th item between 2 and 3, I am going to have to recompute the row height which will consist in re-rendering the height of each item in the row (which is super slow).
I would then end up with three more values in my cache:
{
// Previous values
Id1-Id2-Id3: 400,
Id4-Id5-Id6: 200,
Id7-Id8-Id9: 300,
// New values
Id1-Id2-Id10: 400
Id3-Id4-Id5: 200
Id6-Id7-Id8: 300
Id9-IdPlaceholder-IdPlaceholder: 150
}
So our cache table would keep growing for each combination and except if by luck an insertion or deletion, bring us to a case we already computed, most of the time the cache will not be used.
This is a simplified version of a cache strategy I tried to implement, in reality I also had to keep track of a reference of each item to make sure their content didn’t change (which would make the cached value invalid)
Solution
Instead of caching per row/column we should cache per item. Once an item width and height has been cached, it is quick and easy to get the size of the row or column.
When inserting an item, only the new component will be rendered to be measured. When removing or shuffling items, no component will have to be rendered
Also, our cache table will only contains as many entries as the number of items we have. With the current cache, we could end up with an entry for each possible permutation.
Implementation
You can see how that would be implemented here: https://github.com/bvaughn/react-virtualized/pull/561/files
I also provided an example of how I have implemented the cache for my specific problem.
The PR is not ready:
- Maybe expose the interface to
clearItemHeights
,clearItemHeight
,clearItemWidth
,clearItemWidths
. - Replace
item
bycell
, I found it confusing since you called the Row/Column cache,cellCache
, when actually it doesn’t cache anything about the cell. So I useditem
in the meantime but it is probably a poor choice. - Write tests
But if you are interested to include those changes in react-virtualized
, I can finish the work to make it clean.
Issue Analytics
- State:
- Created 7 years ago
- Comments:5 (4 by maintainers)
Top GitHub Comments
I understand the difference now. That does seem like a useful option to support as well, yes!
Sorry for not catching this the first time. I’m on vacation at the moment and I just quickly glanced at the PR. I’ll give it a closer look and more thought when I get the chance. 😄
This feature will be available in the upcoming RV release. Currently that release is tracked via PR #577. Going to close this issue (even though it’s a bit premature, prior to the release) because it helps me to prune the issues list as I go to make sure I’ve pulled all of the things I want to pull into v9.
Thanks for the detailed write-up and the proposal here. Very helpful!