reactjsreact-queryreact-infinite-scroll-component

InfiniteScroll with multiple params


import InfiniteScroll from 'react-infinite-scroll-component';
import { useSearchParams } from 'react-router-dom';
import { useInfiniteQuery } from '@tanstack/react-query';

export const fetchData = async ({
  page = 1,
  limit = 10,
  sort = 'firstName',
}) => {
  console.log('function page:', page);
  const response = await fetch(
    `http://localhost:5000/data/datas?page=${page}&limit=${limit}&sort=${sort}`
  );
  return response.json();
  // response:
  //{
  //    "data": [],
  //    "hasNextPage": false, // totalItems - page * limit > 0;
  //    "totalItems": 100
  //  }
};

function MyComponent() {
  const [searchParam, setSearchParam] = useSearchParams();
  const page = parseInt(searchParam.get('page')) || 1;
  const limit = parseInt(searchParam.get('limit')) || 25;
  const sort = searchParam.get('sort') || 'firstName';
    
  const {
    isLoading,
    error,
    data,
    fetchNextPage,
    hasNextPage
  } = useInfiniteQuery({
    queryKey: ['data', sort],
    queryFn: () => {
      return fetchData({ page, limit, sort });
    },
    initialPageParam: 1,
    getNextPageParam: (lastPage, allPages) => {
      // console.log('lastPage?.hasNextPage', lastPage?.hasNextPage);
      return lastPage.hasNextPage ? allPages.length + 1 : undefined;
    },
  });

  if (isLoading) {
    return <div>Loading...</div>;
  }

  if (error) {
    return <div>Error: {error.message}</div>;
  }
  console.log('data', data);

  const datas = data?.pages.reduce((acc, page) => {
    return [...acc, ...page.data];
  }, []);

  const fetchMore = () => {
    // const page = Number(searchParam.get('page')) || 1;
    searchParam.set('page', page + 1);
    setSearchParam(searchParam);

    fetchNextPage();
  };

  return (
    <div>
      <h1>Infinite scroll</h1>
      <InfiniteScroll
        dataLength={datas ? datas.length : 0}
        next={fetchMore}
        hasMore={hasNextPage}
        loader={<div>loading more...</div>}
        endMessage={<div>you have reach the end, MF!</div>}
      >
        {datas && datas.map((data) => (
          <h1 key={data?._id}>
            {data?.firstName} - {data?.lastName}
          </h1>
        ))}
      </InfiniteScroll>
    </div>
  );
}

export default MyComponent;

I want to use infinitescroll and useInifiniteQuery, and pass multiple params like sort and limit. I'm fetching the data and get the 1st array of data by default (no page in param). but the problem when I call fetchmore I get the same data (for the 1st time), but then it works when I try to get new data. Therefore I end up on a page that shouldn't exist. For example, if my max page is 10, I reach 11 because of the repetition of the 1st array.

example:

pages={
    0:[1, 2, 3], // same data
    1:[1, 2, 3], // same data
    2:[4, 5, 6],
    3:[7, 8, 9]
}

How to avoid the redundancy of calling the 1st chunk of data twice?


Solution

  • Based on your code, maybe your issues comes from interactions between URL parameters, and React Query's. To solve that issue, remove the page parameter from the URL since React Query handles pagination internally and use enabled option to control when the query runs. I'll give an example like code below

     const [searchParam, setSearchParam] = useSearchParams();
      const limit = parseInt(searchParam.get('limit')) || 25;
      const sort = searchParam.get('sort') || 'firstName';
        
      const {
        isLoading,
        error,
        data,
        fetchNextPage,
        hasNextPage
      } = useInfiniteQuery({
        queryKey: ['data', sort],
        queryFn: ({ pageParam = 1 }) => {
          return fetchData({ 
            page: pageParam, 
            limit, 
            sort 
          });
        },
        initialPageParam: 1,
        getNextPageParam: (lastPage, allPages) => {
          return lastPage.hasNextPage ? allPages.length + 1 : undefined;
        },
      });
    
      // Rest of the component remains same, but modify fetchMore:
      const fetchMore = () => {
        fetchNextPage();
      };
    

    https://tanstack.com/query/v5/docs/framework/react/guides/infinite-queries