当道具在反应虚拟化中发生变化时如何滚动到底部?

How to scroll to bottom when props changed in react-virtualized?

我有来自 react-virtualized 库的带有 List 的组件 App。 我需要在初始渲染时将我的列表滚动到底部。

我做到了,添加了 scrollToIndex 选项。但是当我在我的列表数组中添加新对象时,它不会滚动到我最后添加的对象。我该如何解决?使用 "forceUpdate()" 函数是好的解决方案吗?

import { List } from "react-virtualized";
import loremIpsum from 'lorem-ipsum';

const rowCount = 1000;
const listHeight = 600;
const rowHeight = 50;
const rowWidth = 800;

class App extends Component {
  constructor() {
    super();
    this.renderRow = this.renderRow.bind(this);
    this.list = Array(rowCount).fill().map((val, idx) => {
      return {
        id: idx, 
        name: 'John Doe',
        image: 'http://via.placeholder.com/40',
        text: loremIpsum({
          count: 1, 
          units: 'sentences',
          sentenceLowerBound: 4,
          sentenceUpperBound: 8 
        })
      }
    });
  }

  handle = () => {
    this.list = [...this.list, { id: 1001, name: "haha", image: '', text: 'hahahahahaha' }];
    this.forceUpdate();
    this.refs.List.scrollToRow(this.list.length);
  };


  renderRow({ index, key, style }) {
    console.log('____________', this.list.length);

    return (
      <div key={key} style={style} className="row" >
        <div className="image">
          <img src={this.list[index].image} alt="" />
        </div>
        <div onClick={this.handle}>{this.state.a}</div>
        <div className="content">
          <div>{this.list[index].name}</div>
          <div>{this.list[index].text}</div>
        </div>
      </div>
    );
  }

  render() {
    return (
      <div className="App">
        <div className="list">
          <List
            ref='List'
            width={rowWidth}
            height={listHeight}
            rowHeight={rowHeight}
            rowRenderer={this.renderRow}
            rowCount={this.list.length}
            overscanRowCount={3}
            scrollToIndex={this.list.length}
            />
        </div>
      </div>
    );
  }
}

export default App;

您提到在更改列表项时需要滚动到底部,老实说我不喜欢使用 forceUpdate。正如 React 文档中提到的:

Normally you should try to avoid all uses of forceUpdate() and only read from this.props and this.state in render().

幸运的是,React 生命周期方法之一适用于这种情况,它是调用 componentDidUpdate。但是您需要对代码进行一些重构。我建议将其放在 state/props.

上,而不是使用私有字段

此方法将在更新 props/state 发生后立即调用。但是,初始渲染不会调用此方法。

你需要做的是,对比道具,是换还是不换?然后调用 this.refs.List.scrollToRow(this.list.length);

示例代码

class App extends Component {
  constructor() {
    this.state = {
      list: [] // put your list data here
    }
  }

  // Check the change of the list, and trigger the scroll
  componentDidUpdate(prevProps, prevState) {
    const { list } = this.state;
    const { list: prevList } = prevState;
    if (list.length !== prevList.length) {
      this.refs.List.scrollToRow(list.length);  
    }
  }

  render() {
    // usual business
  }
}

React 生命周期方法的更多参考:

https://reactjs.org/docs/react-component.html#componentdidupdate