Do not use offsetHeight, in other case you get unstable results in Chrome

master
Vitaliy Filippov 2018-10-10 15:41:36 +03:00
parent 135573f35b
commit 3825d158b2
3 changed files with 12 additions and 1 deletions

View File

@ -95,6 +95,10 @@ export function virtualScrollDriver(props, oldState, getRenderedItemHeight)
firstVisibleItem = Math.floor(firstVisibleItem);
let firstVisibleItemHeight = getRenderedItemHeight(firstVisibleItem) || newState.avgRowHeight;
newState.topPlaceholderHeight = scrollTop - firstVisibleItemHeight*firstVisibleItemOffset;
if (newState.topPlaceholderHeight < 0)
{
newState.topPlaceholderHeight = 0;
}
if (firstVisibleItem + newState.viewportItemCount >= props.totalItems - newState.viewportItemCount)
{
// Only one placeholder is required
@ -133,6 +137,10 @@ export function virtualScrollDriver(props, oldState, getRenderedItemHeight)
sum += itemSize;
}
newState.middlePlaceholderHeight = newState.targetHeight - sum - newState.lastItemsTotalHeight - newState.topPlaceholderHeight;
if (newState.middlePlaceholderHeight < 0)
{
newState.middlePlaceholderHeight = 0;
}
const correctedAvg = (sum + newState.lastItemsTotalHeight) / (newState.middleItemCount + newState.viewportItemCount);
if (correctedAvg > newState.avgRowHeight)
{

View File

@ -33,7 +33,7 @@ export class DynamicVirtualScrollExample extends React.PureComponent
// DOM example. As smooth as the previous one (memory example), even without caching
if (this.itemElements[index])
{
return this.itemElements[index].offsetHeight;
return this.itemElements[index].getBoundingClientRect().height;
}
return 0;
}

View File

@ -48,6 +48,9 @@ Description of parameters:
* this function MUST return the height of currently rendered item or 0 if it's not currently rendered
* the returned height MUST be >= props.minRowHeight
* the function MAY cache heights of rendered items if you want your list to be more responsive
* WARNING: you SHOULD NOT use `element.offsetHeight` for measuring. Either use `element.getBoundingClientRect().height`
or use some pre-computed heights, because `offsetHeight` may truncate the height to -1px when
browser scale is not 100%. Also it gives incorrect results with CSS transforms.
Returned object is `newState`. It contains the render parameters for you and also some internal state variables.
What to do with it: