Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

249
Views
React Query - useInfiniteQuery, how to avoid component refresh when fetching next page

Already implemented an infinite scroll feature to my recipes app using Edamam API, but I have this issue:

When I reach the bottom of the page and it starts to fetch the next page, the component does a total refresh, it does show all the items of each page after tho.

What I want is that when I reach the bottom, it starts fetching (showing my spinner at the bottom and stuff) and render the next page at the bottom without refreshing the whole page at all.

Here is my code:

const RecipesGrid = ({ query }) => {
  const getRecipes = async (pageParam) => {
    try {
      const path = pageParam
        ? pageParam
        : `https://api.edamam.com/api/recipes/v2?q=${query}&app_id=${process.env.REACT_APP_APP_ID}&app_key=${process.env.REACT_APP_API_KEY}&type=public`;
      const response = await axios.get(path);
      return response.data;
    } catch (error) {
      console.log(error);
    }
  };

  useEffect(() => {
    const onScroll = (event) => {
      const { scrollHeight, scrollTop, clientHeight } =
        event.target.scrollingElement;
      if (scrollHeight - scrollTop <= clientHeight * 1.2) {
        fetchNextPage();
      }
    };

    document.addEventListener("scroll", onScroll);
    return () => document.removeEventListener("scroll", onScroll);
    // eslint-disable-next-line
  }, []);

  const {
    data,
    isFetching,
    isFetchingNextPage,
    status,
    hasNextPage,
    fetchNextPage,
  } = useInfiniteQuery(
    ["recipes", query],
    ({ pageParam = "" }) => getRecipes(pageParam),
    {
      getNextPageParam: (lastPage) =>
        lastPage._links.next ? lastPage._links.next.href : undefined,
    }
  );

  if (isFetching || status === "loading") {
    return <Spinner />;
  }

  if (status === "error") {
    return <div>Whoops! something went wrong...Please, try again</div>;
  }

  return (
    <div className={styles.Recipes}>
      {data?.pages.map((item, index) => (
        <React.Fragment key={index}>
          {item.hits.map((recipe) => (
            <Recipe recipe={recipe} key={recipe.recipe.uri} />
          ))}
          {item.hits.length === 0 ? (
            <Empty message="No results found!" />
          ) : null}
          {!hasNextPage && item.hits.length !== 0 && (
            <Empty message="No more recipes!" />
          )}
        </React.Fragment>
      ))}
      {isFetchingNextPage && <Spinner />}
    </div>
  );
};

export default RecipesGrid;
about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

I think you're unmounting the whole list because you only render a loading spinner here:

  if (isFetching || status === "loading") {
    return <Spinner />;
  }

isFething is always true whenever a request is in-flight. This is also true for when you are fetching the next page, so you get into this early return and remove your list. Removing isFetching from the if statement should solve it, since you display a background loading indicator anyways via:

{isFetchingNextPage && <Spinner />}

Additionally, your error handling won't work because you transform errors into resolved promises by catching them for logging and not re-throwing them:

} catch (error) {
  console.log(error);
}

Please use the onError callback for things like that.

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!