简体   繁体   中英

Infinite scrolling and updating it with newly fetched data in React

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>

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.

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;
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM