Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

react-virtualized scrollToIndex not working on List

When attempting to scrollToIndex the screen goes blank.

Here's a codesandbox that reproduces the problem. Just type 100 in the input box on top and click the "scroll to row" button. https://codesandbox.io/s/zr2r2wp1x

It's a somewhat complicated view - it uses InfiniteLoader, WindowScroller, Autosizer, CellMeasurer, CellMeasurerCache and List.

Here's the code:

import React, { Component } from 'react';
import {
  AutoSizer,
  CellMeasurer,
  CellMeasurerCache,
  InfiniteLoader,
  List,
  WindowScroller
} from 'react-virtualized';


const cache = new CellMeasurerCache({
  fixedWidth: true,
  defaultHeight: 100
});

class Hello extends Component {
  constructor(props) {
    super(props);
    this.state = {
      scrollToIndex: undefined
    }
    this.list = [];
    this.makeList = this.makeList.bind(this);
    this.makeList();
    this.handleClick = this.handleClick.bind(this);
  }

  makeList() {
    for (let i = 0; i < 200; i++) {
      this.list.push("yo");
    }
  }


  handleClick() {
    this.setState({
      scrollToIndex:this.inputRow.value
    })
  }

  isRowLoaded({ index }) {
    return !!this.list[index];
  }

  loadMoreRows({ startIndex, stopIndex }) {
    this.makeList();
  }

  rowRenderer({ index, isScrolling, isVisible, key, parent, style }) {
    if (isScrolling) {
      return null;
    }

    if (isVisible) {
      return (
        <CellMeasurer
          key={key}
          cache={cache}
          parent={parent}
          columnIndex={0}
          rowIndex={index}
        >
          <div style={style}>
            this is row: {index}
          </div>
        </CellMeasurer>
      );
    }
    return null;
  }


  render() {

    if (this.list.length === 0) {
      return <div>No data available.</div>;
    }

    const scrollToIndex = this.state.scrollToIndex;

    return (
      <div>
        <div>
          <input
            type="number"
            ref={(input) => { this.inputRow = input; }} />
          <input
            type="button"
            value="Scroll To Row"
            onClick={this.handleClick}
          />
        </div>
        <InfiniteLoader
          isRowLoaded={isRowLoaded => this.isRowLoaded(isRowLoaded)}
          loadMoreRows={loadMoreRows => this.loadMoreRows(loadMoreRows)}
          rowCount={10000}
          threshold={1}
        >
          {({ onRowsRendered, registerChild }) => (
            <WindowScroller>
              {({ height, isScrolling, onChildScroll, scrollTop }) => (
                <AutoSizer disableHeight>
                  {({ width }) => {
                    console.log("scroll to index", scrollToIndex)
                    return (
                      <List
                        autoHeight
                        height={height}
                        onRowsRendered={onRowsRendered}
                        ref={registerChild}
                        width={width}
                        rowCount={this.list.length}
                        rowHeight={cache.rowHeight}
                        rowRenderer={rowRenderer => this.rowRenderer(rowRenderer)}
                        scrollTop={scrollTop}
                        deferredMeasurementCache={cache}
                        style={{ paddingLeft: '0', paddingRight: '0' }}
                        scrollToAlignment="start"
                        scrollToIndex={scrollToIndex}
                      />
                    )
                  }}
                </AutoSizer>
              )}
            </WindowScroller>
          )}
        </InfiniteLoader>
      </div>
    );
  }
}

export default Hello;
like image 552
Bob Glass Avatar asked Sep 02 '25 09:09

Bob Glass


1 Answers

Here's an updated CodeSandbox displaying how to accomplish your desired behavior. I had to fix numerous issues with your starter code to get the example to work properly - the short answer is you were missing passing WindowScroller's render prop onChildScroll to the List component's onScroll prop. This setup will allow both the components to communicate with each other to effectively update the list properly.

like image 179
Alex Mejias Avatar answered Sep 04 '25 23:09

Alex Mejias