Search code examples
reactjsinfinite-scroll

useInfiniteScroll not triggering onLoadMore


I´m using the dependency react-infinite-scroll-hook in the functional component below, where I do retrieve data from PokéAPI. However, the data is only loaded the first time the function loadData is called in useEffect, but scrolling to the component with sentryRef does not trigger onLoadMore in useInfiniteScroll. What I'm missing here?

import React, { useState, useEffect } from 'react';
import { Grid, CircularProgress, capitalize, List, ListItem, ListItemIcon, ListItemText } from '@material-ui/core';
import useInfiniteScroll from 'react-infinite-scroll-hook';
import axios from 'axios';
import { Lens } from '@material-ui/icons';

function NationalPokedex(props) {
    const [pokemons, setPokemons] = useState([]);
    const [loading, setLoading] = useState(false);
    const [hasNext, setHasNext] = useState(true);
    const [next, setNext] = useState('https://pokeapi.co/api/v2/pokemon/');

    const loadData = () => {
        setLoading(true);
        console.log("FETCH")
        axios.get(next).then(response => {
            setPokemons([...pokemons, ...response.data.results]);
            if(response.data.next) {
                setNext(response.data.next);
            } else {
                setHasNext(false);
                setNext(null);
            }
            setLoading(false);
        });  
    }

    const [sentryRef] = useInfiniteScroll({
        loading,
        hasNext,
        onLoadMore: loadData,
        disabled: !!hasNext,
        rootMargin: '0px 0px 100px 0px',
    });

    useEffect(loadData, []);

    const renderData = () => {
        var result = [];
        pokemons.map((pokemon) => {
            result.push(<ListItem key={pokemon.name}><ListItemIcon><Lens></Lens></ListItemIcon><ListItemText>{capitalize(pokemon.name)}</ListItemText></ListItem>);
        });
        console.log("LOAD_DATA");
        console.log(hasNext, next, loading, pokemons);
        return result;
    }

    return (
        <>
        <List spacing={3}>
            {renderData()}
        </List>
        {(hasNext || loading) && (
            <Grid container item xs={12} ref={sentryRef} justifyContent='center' key='progress'>
                <CircularProgress/>
            </Grid>
        )}
        </>
    );
}

Solution

  • I ended up using another dependency, react-infinite-scroller, that works perfectly, so I guess the issue was not on my side.

    The code looks like this, in case it is useful for someone:

    import React, { useState } from 'react';
    import { Grid, CircularProgress, capitalize, List, ListItem, ListItemIcon, ListItemText } from '@material-ui/core';
    import InfiniteScroll from 'react-infinite-scroller';
    import axios from 'axios';
    import { Lens } from '@material-ui/icons';
    
    function NationalPokedex(props) {
        const [pokemons, setPokemons] = useState([]);
        const [hasNext, setHasNext] = useState(true);
        const [next, setNext] = useState('https://pokeapi.co/api/v2/pokemon/');
    
        const loadData = () => {
            axios.get(next).then(response => {
                setPokemons([...pokemons, ...response.data.results]);
                if(response.data.next) {
                    setNext(response.data.next);
                } else {
                    setHasNext(false);
                    setNext(null);
                }
            });  
        }
    
        const renderData = () => {
            var result = [];
            pokemons.map((pokemon) => {
                result.push(<ListItem key={pokemon.name}><ListItemIcon><Lens></Lens></ListItemIcon><ListItemText>{capitalize(pokemon.name)}</ListItemText></ListItem>);
            });
            return result;
        }
    
        return (
            <InfiniteScroll
                pageStart={0}
                loadMore={loadData}
                hasMore={hasNext}
                loader={<Grid container item xs={12} justifyContent='center' key='progress'><CircularProgress/></Grid>}
                threshold={0}
            >
                <List>{renderData()}</List>           
            </InfiniteScroll>
        );
    }
    
    export default NationalPokedex;