Search code examples
javascriptreactjsreact-nativeinfinite-scrollreact-query

Problem with React Query's Infinite Query, using Edamam API


I currently have some issues trying to add the infinite query feature to a recipes app I'm working on using Edamam API.

All the examples I have looked for (even React Query's documentation) implement the infinite scroll using a page/cursor number system... I understand this is the ideal way, but... Edamam API doesn't work this way with paginated queries.

Instead, the API has the following structure for each recipe query we look for (let's assume we are searching for "chicken", this would be the JSON structure):

from: 1,
to: 20,
count: 10000,
_links: {
          next: {
                  href: "https://api.edamam.com/api/recipes/v2?q=chicken&app_key=APIKEYc&_cont=CHcVQBtNNQphDmgVQntAEX4BYldtBAAGRmxGC2ERYVJ2BwoVX3cVBWQSY1EhBQcGEmNHVmMTYFEgDQQCFTNJBGQUMQZxVhFqX3cWQT1OcV9xBB8VADQWVhFCPwoxXVZEITQeVDcBaR4-SQ%3D%3D&type=public&app_id=APPID"
                 title: "Next Page"
                }
},
hits: [{}] ... (This is where the actual recipes are)

As you can see, there is no numbering system for paginated queries, instead, it's a whole URL and it's giving me a hard time since I'm also new to React Query.

I tried the following, but it just fetches the same data over and over again as I reach the bottom of the page:

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


const { ref, inView } = useInView();

  useEffect(() => {
    inView && fetchNextPage();
  }, [inView]);

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

Since the next page param is a whole URL, I just say that IF there is a pageParam, then use that URL for the request, if not, then do a normal request using the query value the user is searching for.

Please help!


Solution

  • Since the next page param is a whole URL, I just say that IF there is a pageParam, then use that URL for the request, if not, then do a normal request using the query value the user is searching for.

    I'd say that this is the correct approach. The only code issue I can see in your example is that you destruct page param, and then pass the page param string to getRecipes:

    ({ pageParam = "" }) => getRecipes(pageParam),
    

    but in getRecipes, you expect an object to come in (which you again destructure):

    const getRecipes = async ({ pageParam }) => {
    

    You can fix that by either changing the call side, or the function syntax, and then it should work.