首页 > 解决方案 > React Query - useInfiniteQuery,如何在获取下一页时避免组件刷新

问题描述

已经使用 Edamam API 为我的食谱应用程序实现了无限滚动功能,但我有这个问题:

当我到达页面底部并开始获取下一页时,组件会进行完全刷新,它确实会显示每个页面的所有项目。

我想要的是,当我到达底部时,它开始获取(在底部显示我的微调器和其他东西)并在底部渲染下一页而不刷新整个页面。

这是我的代码:

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;

标签: javascriptreactjsreact-nativeinfinite-scrollreact-query

解决方案


我认为您正在卸载整个列表,因为您只在此处呈现加载微调器:

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

isFething每当请求进行中时始终为真。当您获取下一页时也是如此,因此您进入此早期返回并删除您的列表。从 if 语句中删除isFetching应该可以解决它,因为无论如何您都会通过以下方式显示后台加载指示器:

{isFetchingNextPage && <Spinner />}

此外,您的错误处理将不起作用,因为您通过捕获它们进行日志记录而不是重新抛出它们将错误转换为已解决的承诺:

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

请使用onError回调来处理类似的事情。


推荐阅读