If deferredMeasurementCache is turned on, the problem gets exponentially worse since n becomes the size of the collection.
If you're not passing the CellMeasurerCache
to Grid
as a deferredMeasurementCache
prop, then Grid
isn't guaranteed to work correctly. It's necessary for it to know about the cache for a couple of cases. (Maybe check out this part of the docs to make sure you aren't misunderstanding how CellMeasurer
is supposed to work when used to calculate the width/height of a row/column.)
That being said, what you're describing sounds like a bug, but I'm not sure it actually is. At a high level, it's caused by the CellMeasurer
measure
method calling Grid.recomputeGridSize()
which synchronously triggers forceUpdate()
(causing all visible cells to re-render).
At first I thought the solution might be to just debounce or queue a setState
action instead. Unfortunately that only pushes the problem away a little; the possibility still exists. I can't debounce for too long, or I risk the Grid
showing cells to the user that are clearly the wrong size. (A debounce that's too big might even allow a user to keep scrolling ahead of it, outrunning the re-render.) It's also possible that images will load far apartĀ (after a delay) in a real app, defeating any debounce I might do anyway.
The problem here is that any time a cell reports it has a different size, the Grid
needs to relayout the other cells (potentially shifting them up or down). In this simple example it seems unnecessary- because all images end up having a uniform width and height. This isn't typical though. Since you've configured your CellMeasurerCache
to measure height, and since the height of each column impacts the height of the row (and thus all other columns, as explained in the docs I linked to above), Grid
has to re-render all cells each time one reports a change.
Put another way, if you added more rows, and changed your example to be more like this:
const makeImages = (count=10, startIndex=0) => {
const width = 100;
const imagesArray = _.times(count, (index) => {
const height = 100 + Math.round(Math.random() * 200);
return {
key: startIndex+index,
src: `http://placehold.it/${width}x${height}/${((1<<24)*Math.random()|0).toString(16)}/fff?text=${startIndex+index}`,
}
});
return imagesArray;
};
Then maybe it's easier to see why a change to a cell in row 1, column 1 could potential impact the height of all cells in row 1, and the position of all cells in the grid.