Infinite scrolling with React JS Infinite scrolling with React JS reactjs reactjs

Infinite scrolling with React JS


Basically when scrolling you want to decide which elements are visible and then rerender to display only those elements, with a single spacer element on top and bottom to represent the offscreen elements.

Vjeux made a fiddle here which you can look at: jsfiddle.

Upon scrolling it executes

scrollState: function(scroll) {    var visibleStart = Math.floor(scroll / this.state.recordHeight);    var visibleEnd = Math.min(visibleStart + this.state.recordsPerBody, this.state.total - 1);    var displayStart = Math.max(0, Math.floor(scroll / this.state.recordHeight) - this.state.recordsPerBody * 1.5);    var displayEnd = Math.min(displayStart + 4 * this.state.recordsPerBody, this.state.total - 1);    this.setState({        visibleStart: visibleStart,        visibleEnd: visibleEnd,        displayStart: displayStart,        displayEnd: displayEnd,        scroll: scroll    });},

and then the render function will display only the rows in the range displayStart..displayEnd.

You may also be interested in ReactJS: Modeling Bi-Directional Infinite Scrolling.


Check out our React Infinite Library:

https://github.com/seatgeek/react-infinite

Update December 2016

I've actually been using react-virtualized in a lot of my projects recently and find that it covers the majority of use cases a lot better. Both libraries are good, it depends on exactly what you're looking for. For instance, react-virtualized supports variable height JIT measuring via an HOC called CellMeasurer, example here https://bvaughn.github.io/react-virtualized/#/components/CellMeasurer.

Update November 2018

A lot of the lessons from react-virtualized have been ported to the smaller, faster, more efficient react-window library from the same author.


import React, { Component } from 'react';import InfiniteScroll from 'react-infinite-scroller';const api = {    baseUrl: '/joblist'};class Jobs extends Component {    constructor(props) {            super(props);            this.state = {                listData: [],                hasMoreItems: true,                nextHref: null        };    }    fetchData(){            var self = this;                       var url = api.baseUrl;            if(this.state.nextHref) {                url = this.state.nextHref;            }            fetch(url)            .then( (response) => {                return response.json() })                       .then( (json) => {                        var list = self.state.listData;                                                json.data.map(data => {                            list.push(data);                        });                        if(json.next_page_url != null) {                            self.setState({                                nextHref: resp.next_page_url,                                listData: list                                                           });                        } else {                            self.setState({                                hasMoreItems: false                            });                        }                    })                    .catch(error => console.log('err ' + error));        }    }    componentDidMount() {       this.fetchData();    }    render() {    const loader = <div className="loader">Loading ...</div>;    let JobItems;     if(this.state.listData){          JobItems = this.state.listData.map(Job => {        return (            <tr>                <td>{Job.job_number}</td>                <td>{Job.title}</td>                <td>{Job.description}</td>                <td>{Job.status}</td>            </tr>        );      });    }    return (      <div className="Jobs">        <div className="container">            <h2>Jobs List</h2>            <InfiniteScroll                pageStart={0}                loadMore={this.fetchData.bind(this)}                hasMore={this.state.hasMoreItems}                loader={loader}>                <table className="table table-bordered">                <thead>                    <tr>                        <th>Job Number</th>                        <th>Title</th>                        <th>Description</th>                        <th>Status</th>                    </tr>                </thead>                <tbody>                {JobItems}                </tbody>                </table>            </InfiniteScroll>        </div>    </div>    );  }}export default Jobs;