0

I am facing an issue with react-virtualized that when I try to render List along with CellMeasurer having items with dynamic heights and I scroll through the list the heights are getting incorrectly calculated intermittently (sometimes they are correctly measured, sometimes it gets incorrectly measured). It sometimes happens that few items take the height of the first item in the list. When the first item is of greater height than the other I see extra white spaces between elements and when height is less they start to overlap over each other.

Adding some minimilistic sample code which I am trying to implement. Any help would be appreciated!!

const Component = (props) => {

  const rowCacheRef = useRef(
    new CellMeasurerCache({
      fixedWidth: true,
      defaultHeight: DEFAULT_ROW_HEIGHT,
      keyMapper: (rowIndex: number): string => decoratedItemsRef.current[rowIndex]?.key,
      ...cellMeasurerProps,
    })
  );


  const rowRenderer = ({ index, key, style: _rowStyles, parent }) => {
      const decoratedItem = decoratedItemsRef.current?.[index];
      return (
        <CellMeasurer key={key} cache={rowCacheRef.current} parent={parent} columnIndex={0} rowIndex={index}>
          {({ measure }): React.ReactElement | null => (
            <div key={key} style={_rowStyles}>
              <MyComponent />
            </div>
          )}
        </CellMeasurer>
      );
    };

  return (
    <List
      ref={listRef}
      height={height}
      width={width}
      autoHeight={autoHeight}
      scrollTop={scrollTop}
      isScrolling={isScrolling}
      rowCount={decoratedItemsRef.current.length}
      rowHeight={_rowHeight}
      rowRenderer={rowRenderer}
      deferredMeasurementCache={rowCache}
      onScroll={_onScroll}
      containerStyle={containerStyle}
      style={style}
      tabIndex={tabIndex}
      overscanRowCount={overscanRowCount}
    />
  );
}

const MainComponent = () => {
  return (
    <WindowScroller scrollElement={scrollElement}>
      {({ height, isScrolling, onChildScroll, scrollTop }): React.ReactElement => (
        <AutoSizer disableHeight>
          {({ width }): React.ReactElement =>
            <Component 
              width={width},
              height={height}
              scrollTop={scrollTop},
              isScrolling={isScrolling},
              autoHeight
            />
           }
          </AutoSizer>
        )}
      </WindowScroller>
      );
    }
Shubham Jain
  • 930
  • 1
  • 14
  • 24

1 Answers1

1

I had a similar issue, I fixed it by making sure that the measure method is called after the row contents are fully loaded.

<CellMeasurer
cache={this._cache}
columnIndex={0}
key={dataKey}
parent={parent}
rowIndex={rowIndex}>
{({measure, registerChild}) => (
    <Detalles rowData={rowData} color={color} measure={measure}/>
)}
</CellMeasurer>

function Detalles(props) {
return (
    <div
    className={styles.tableColumn}
    style={{
        display: "flex",
        flexDirection: "column",
        backgroundColor: props.color
    }}>
    {
        props.rowData.detalles.map((q) => {                    
            return <div>{q}</div>
        })
    }
    </div>
);
useEffect(() => {   
    props.measure();
});
}
Dharman
  • 30,962
  • 25
  • 85
  • 135