0

I have component App with List from react-virtualized library. And I need on initial render, that my List scroll to bottom.

And I did it, when added scrollToIndex option. But when I add new object in my list array, it does not scroll to my last added object. How can I fix it? And is it good solution to use "forceUpdate()" function?

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;
Victor
  • 745
  • 2
  • 7
  • 16

1 Answers1

2

You mentioning you need to scroll to the bottom when the list item is changed and to be honest i don't like to use forceUpdate. As mentioned on the React docs:

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

Luckily, one of React lifecycle method is suitable for this case, it is call componentDidUpdate. But you need to do some refactor of your code. Instead using private field, i suggest to put it on state/props.

This method will invoked immediately after updating props/state occurs. However, This method is not called for the initial render.

What you need to do is, compare the props, is it change or not? Then call this.refs.List.scrollToRow(this.list.length);

Sample code

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
  }
}

more reference for React lifecyle methods:

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

I Putu Yoga Permana
  • 3,980
  • 29
  • 33
  • Thank you for this answer. Will it be work, for example, if the list will be come from reducer state? And is it good idea to load all my huge array of objects on client from database on componentDidMount ? Or better idea to upload parts (send request on server) on scroll? – Victor Aug 09 '18 at 16:04
  • Yes, it is best combination if coming from reducer state, easier to debug. The main problem if you load huge array on `componentDidMount` it will make the js thread blocked and some animation or interaction blocked. Better make the pagination, and load more item when reach bottom like you suggest. – I Putu Yoga Permana Aug 09 '18 at 16:08
  • what should we do if we want to scroll to top (first row) when props changed and/or list item changed? ScrollToRow allows us scroll more but what if we want to scroll back? – benchpresser Feb 24 '20 at 00:25