Infinite scrolling with React JS

后端 未结 3 1672
遥遥无期
遥遥无期 2020-11-29 16:07

I am looking at ways to implement infinite scrolling with React. I have come across react-infinite-scroll and found it inefficient as it just adds nodes to the DOM and doesn

相关标签:
3条回答
  • 2020-11-29 16:18

    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.

    0 讨论(0)
  • 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;
    
    0 讨论(0)
  • 2020-11-29 16:37

    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.

    0 讨论(0)
提交回复
热议问题