Home > Mobile >  Infinite scrolling and updating it with newly fetched data in React
Infinite scrolling and updating it with newly fetched data in React

Time:12-02

I'm trying to render an infinite scroll component and update its data with newly fetched news upon scrolling to the end of it. It works on the first scroll, but gets stuck at Loading... after that. I don't understand what is going on that makes it stop fetching after first scroll.

Code that's supposed to get new data looks like this:

  const [latestNews, setLatestNews] = useState<any[]>([]);
  const [page, setPage] = useState<number>(1);

         const getLatestNews = async (page: number) => {
        
            let url = `https://api.nytimes.com/svc/search/v2/articlesearch.json?api-key=${API_KEY}&page=${page}`;
            
            const response = await fetch(url);
            const data = await response.json();
            setLatestNews(data.response.docs);
            setPage(page   1);
          }

And my infinite scroll component looks like this

            <InfiniteScroll dataLength={latestNews.length} next={() => getLatestNews(page)} hasMore={true} loader={<h4>Loading...</h4>} scrollableTarget="scrollableDiv">
              {
                latestNews.map((article, index) => (
                  <div className="latest-news-article flex flex-col gap-3 mb-4" key={index}>
                    <p className="latest-news-article-date">
                      {article.pub_date.slice(11, 16)}
                    </p>
                    <h1>
                      {article.headline.main}
                    </h1>
                  </div>
                ))
              }
            </InfiniteScroll>

CodePudding user response:

I think I found the solution for now.

In my words, that scrolling was "too fast" and it updated the state quickly, much faster than API can take request and I was getting 429 Too Many Requests. Solution:

  const getLatestNews = async () => {
    setTimeout(async () => {
      const response = await fetch(`https://api.nytimes.com/svc/search/v2/articlesearch.json?api-key=${API_KEY}&page=${page}`);
      const data = await response.json();
      setLatestNews((prev) => [...prev, ...data.response.docs]);
      setPage(page   1);
    }, 5000);

  }

I added setTimeout to 5000ms, that way API requests are not sent instantly, and state changes just fine. It also renders new news accordingly.

CodePudding user response:

Your solution works but there is another solution that is more logical.

You can add a ref using useRef and change its value when you're sending your request in order to prevent from sending another request at the same time:

const sendRequestRef = useRef(true);

const getLatestNews = async () => {
  if(sendRequestRef.current === true) {
    sendRequestRef.current = false;
    const response = await fetch(`https://api.nytimes.com/svc/search/v2/articlesearch.json?api-key=${API_KEY}&page=${page}`);
    const data = await response.json();
    setLatestNews((prev) => [...prev, ...data.response.docs]);
    setPage(page   1);
    sendRequestRef.current = true;
  }
}
  • Related