How to load more search results when scrolling down the page in React.js?

37,251

Solution 1

This is called infinite scroll. If you don't wanna build this from the scratch, you can use external libs:

https://www.npmjs.com/package/react-infinite-scroller

https://www.npmjs.com/package/react-infinite-scroll-component

If you wanna build it yourself, you can follow these tutorials:

https://alligator.io/react/react-infinite-scroll/

https://upmostly.com/tutorials/build-an-infinite-scroll-component-in-react-using-react-hooks

Solution 2

Without plugins:

componentWillMount(){
  window.addEventListener('scroll', this.loadMore);
}

componentWillUnmount(){
    window.removeEventListener('scroll', this.loadMore);
}

loadMore(){
    if (window.innerHeight + document.documentElement.scrollTop === document.scrollingElement.scrollHeight) {
        // Do load more content here!
    }
}
Share:
37,251
Adrian
Author by

Adrian

Updated on January 25, 2020

Comments

  • Adrian
    Adrian over 4 years

    I would like to load more searching results when scrolling down the page. I work with google API book and I would like to load just 10 searching results and if user scroll to the last search element than next 10 results load automatically. How to do that? I need a code example how proper solution should look like. Thanks for help.

    My App.js file is as follow:

     import React, { useState } from "react";
     import axios from "axios";
     import './App.css';
     import 'bootstrap/dist/css/bootstrap.min.css';
    
    
    const App = () => {
    const [searchTerm, setSearchTerm] = useState("");
    const [books, setBooks] = useState({ items: [] });
    const onInputChange = e => {
        setSearchTerm(e.target.value);
    };
    
    let API_URL = 'https://www.googleapis.com/books/v1/volumes';
    
    const fetchBooks = async () => {
    
        if (document.getElementById("choose_search").value === "title") {
    
            const result = await axios.get(`${API_URL}? 
    q=${searchTerm}&maxResults=40`);
            setBooks(result.data);
        }
        else {
            const result = await axios.get(`${API_URL}? 
    q=inauthor:${searchTerm}&maxResults=40`);
            setBooks(result.data);
        }
    
    };
    
    const onSubmitHandler = e => {
        e.preventDefault();
        fetchBooks();
    };
    
    return (
        <section>
    
                <form onSubmit={onSubmitHandler} id="submit">
                    <label>
                        <input
                            type="search"
                            placeholder="Search books"
                            value={searchTerm}
                            onChange={onInputChange}
                        />
                        <button type="submit" class="btn btn- 
      success">Search</button>
                    </label>
            </form>
    
            <div id="choose_position" class="row">
                <div class="col-2">
                <select id="choose_search" class="form-control-sm">
                    <option value="" disabled selected>Select search 
     type</option>
                    <option value="title">Title</option>
                    <option value="author">Author</option>
                    </select>
                </div>
            </div>
    
            <ul>
                {books.items.map((book, index) => {
                    return (
                    <div>
                            <div class="border rounded">
    
                            <div class="row">
                                <div class="col-12 d-flex justify-content- 
     center p-4" >
                                    <u><h5>{book.volumeInfo.title}</h5></u>
                                </div>
                            </div>
                            <div class="row">
                                <div class="col-4">
                                    <img
                                        id="img_book"
                                        alt={`${book.volumeInfo.title} book`}
                                        src= 
     {`http://books.google.com/books/content?id=${
                                            book.id
    
      }&printsec=frontcover&img=1&zoom=1&source=gbs_api`}
                                    />
                                </div>
                                <div class="col-8">
                                    {typeof book.volumeInfo.description === 
     'string' && book.volumeInfo.description.length > 0 ? 
     book.volumeInfo.description : <img src="../no_description.jpg" 
     id="description_img"/>}
    
                                </div>
    
                            </div>
    
                            <div class="row">
                                <div class="col-4"></div>
                                <div class="col-4"><b>Preview:</b> {typeof 
      book.volumeInfo.previewLink === 'string' && 
      book.volumeInfo.previewLink.length > 0 ? <a href= 
     {book.volumeInfo.previewLink}>Link</a> : 'No data'}
                                </div>
                                <div class="col-4"><b>Published date:</b> 
      {typeof book.volumeInfo.publishedDate === 'string' && 
      book.volumeInfo.publishedDate.length > 0 ? book.volumeInfo.publishedDate 
      : 'No data'}
                                </div>
    
                            </div>
    
                             <div class="row pb-3">  
                                <div class="col-4"></div>
                                    <div class="col-4"><b>Free download:</b> 
      {typeof book.accessInfo.pdf.downloadLink === 'string' && 
      book.accessInfo.pdf.downloadLink.length > 0 ? <a href= 
      {book.accessInfo.pdf.downloadLink}>Link</a> : 'Not avaliable'}
                                    </div>
                                    <div class="col-4"><b>Ebook version:</b> 
      {typeof book.saleInfo.isEbook === 'boolean' && book.saleInfo.isEbook === 
      true ? 'Yes' : 'No'}
                                </div>
                                <br/>
                            </div>
    
                                </div><br/>
                        </div> 
                    );
                })}
            </ul>
         </section>
       );
       };
       export default App;
    
  • Hoang Minh
    Hoang Minh almost 4 years
    Thanks. I have to modify the if condition a bit to work in my case window.innerHeight + document.documentElement.scrollTop + 5 >= document.scrollingElement.scrollHeigh
  • Alex
    Alex almost 4 years
    @HoangMinh I did the same, but I recommend u to use "+1", in that way u will load data only once
  • Hoang Minh
    Hoang Minh almost 4 years
    Thanks Alex. I did not know about that. I'll check if my application is sending multiple requests to load data.