react-virtualized scrollToIndex不在List上工作

时间:2018-03-22 14:55:14

标签: react-virtualized

尝试scrollToIndex时,屏幕变为空白。

这是一个可以重现问题的代码框。只需在顶部的输入框中键入100,然后单击“滚动到行”按钮。 https://codesandbox.io/s/zr2r2wp1x

这有点复杂 - 它使用InfiniteLoader,WindowScroller,Autosizer,CellMeasurer,CellMeasurerCache和List。

以下是代码:

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;

1 个答案:

答案 0 :(得分:3)

这是updated CodeSandbox显示如何完成您想要的行为。我必须解决你的初学者代码的许多问题,以使示例正常工作 - 简短的回答是你错过了将WindowScroller的渲染道具onChildScroll传递给List组件的{{ 1}}道具。此设置将允许两个组件相互通信,以便有效地更新列表。