2

I am using react-infinite scroll component like this:

const [hasMore, setHasMore] = useState(true)
const [pageNumber, setPageNumber] = useState(1)

  const fetchDataOnScroll = async () => {
    try {
      const res = await axios.get(
        `${process.env.REACT_APP_API}/api/v1/posts?page=${pageNumber}`
        
      )
  
      (res.data.doc.length === 0) setHasMore(false)

      setPosts((prev) => [...prev, ...res?.data?.doc])
      setPageNumber((prev) => prev + 1)
    } catch (error) {
      alert('Error fetching Posts')
      console.log('ERROR', error.data.response)
    }
  }

  return (
<InfiniteScroll
   hasMore={hasMore}
   next={fetchDataOnScroll}
   endMessage='No More Post'
   dataLength={posts.length}
   loader={<h1>LOADING...</h1>}
>
{posts.map((post) => (
 <FeedCard key={post._id} post={post} />
))}
 </InfiniteScroll>
)

I only get LOADING... on my browser. But when I write my next as next={fetchDataOnScroll()}, It renders continuously until the page freezes. I have to close my browser.

How can i fix this?

merlin
  • 227
  • 2
  • 4
  • 13
  • please come with a working snippet, if you have a snippet that shows your problem clearly, it will solve your problem much faster compare to come without a snippet, for example, you can create a snippet from code sandbox – Nisharg Shah Jul 10 '22 at 11:58
  • You probably miss `containerHeight` and `elementHeight`. Or you are using a different library than you said. – Konrad Jul 10 '22 at 14:31

4 Answers4

0

I suggest using useEffect and change page in next function. I think this make some amount of delay that allow infinite scroll render current component. This code solve my problem.

<InfiniteScroll
   ...
   next={setPage(page+1)}
...>

And in useEffect function after changing page you can call api

useEffect(() => {
fetchDataOnScroll()
},[page]
sajadab
  • 383
  • 2
  • 11
0

Try next={() => fetchDataOnScroll()} instead next={fetchDataOnScroll()}

volodymyr
  • 11
  • 1
0

I also had the same problem. You have to put a wrapper for the component and set the overflow equal to hidden, then set the height of the component equal to the height of the wrapper.

    /* Create a new style sheet or add the following code to your existing style sheet */
.wrapper {
  overflow: hidden; /* Hide any overflow beyond the content's size */
  height: 100vh; /* Set the height equal to the viewport height to limit scrolling */
}



    import React, { useState, useEffect, useRef } from 'react';
import axios from 'axios';
import InfiniteScroll from 'react-infinite-scroll-component';
import FeedCard from './FeedCard'; // Assuming this component exists properly

const YourComponent = () => {
  const [hasMore, setHasMore] = useState(true);
  const [pageNumber, setPageNumber] = useState(1);
  const [posts, setPosts] = useState([]);
  const wrapperRef = useRef(null); // Use useRef to access the wrapper's height

  const fetchDataOnScroll = async () => {
    try {
      const res = await axios.get(
        `${process.env.REACT_APP_API}/api/v1/posts?page=${pageNumber}`
      );

      if (res.data.doc.length === 0) setHasMore(false);

      setPosts((prev) => [...prev, ...res?.data?.doc]);
      setPageNumber((prev) => prev + 1);
    } catch (error) {
      alert('Error fetching Posts');
      console.log('ERROR', error.data.response);
    }
  };

  useEffect(() => {
    // Call the initial data fetch as well.
    fetchDataOnScroll();
  }, []);

  useEffect(() => {
    // Set InfiniteScroll height equal to wrapper's height
    if (wrapperRef.current) {
      const wrapperHeight = wrapperRef.current.clientHeight;
      // Pass the height to InfiniteScroll
      // This ensures both components have the same height.
      setInfiniteScrollHeight(wrapperHeight);
    }
  }, [posts]); // Execute this useEffect whenever the number of posts changes

  const setInfiniteScrollHeight = (height) => {
    // Access InfiniteScroll using ref and set the height
    const infiniteScroll = document.querySelector('.infinite-scroll-component');
    if (infiniteScroll) {
      infiniteScroll.style.height = `${height}px`;
    }
  };

  return (
    <div ref={wrapperRef} className="wrapper">
      <InfiniteScroll
        dataLength={posts.length}
        next={fetchDataOnScroll}
        hasMore={hasMore}
        endMessage="No More Post"
        loader={<h1>LOADING...</h1>}
      >
        {posts.map((post) => (
          <FeedCard key={post._id} post={post} />
        ))}
      </InfiniteScroll>
    </div>
  );
};

export default YourComponent;
0

I faced the same issue, the solution that solved this problem for me was adding a dynamic data length attribute.

<InfiniteScroll .... dataLength={this.state.items.length} ...>

Chandan Maruthi
  • 183
  • 1
  • 2
  • 9