首页 > 解决方案 > Apollo Client - fetchMore 组件更新问题

问题描述

在我的NextJS应用程序与MongoDB API 后端接口 - 通过GraphQL管理,我正在尝试实现Apollo fetchMore功能,以更新负责从数据集合加载更多项目的组件。

在页面渲染中,组件本身显示了一个包含 10 个元素的“画廊”作为其原生功能,通过 GraphQL 起始查询填充。然后,我添加了一个“加载更多”按钮来触发该fetchMore功能。UX 预计,如果用户单击正确的按钮,除了之前的 10 个元素之外,还将加载更多的 10 个元素 - 基本上是一个经典的异步无限加载示例。

通过检查应用程序,我注意到两个查询都已成功返回 - 初始化一个和“加载更多 10 个项目”也由它管理fetchMore- 但后者在执行后触发组件的更新,它正在重新初始化启动查询而不是fetchMore一个。

为了澄清这一点:在“加载更多”上单击,而不是查看加载的下 10 个画廊元素 - 所以最终显示总共 20 个 - 组件刷新并显示起始 10 个元素,就像它的开始初始化一样 - 完全忽略了fetchMore动作,即使这个被调用、执行并收到一个填充的 200 响应。

因为这是我第一次使用它,我不知道我是否在我的实现中遗漏了一些东西,或者我需要修复一些东西。无论如何,这里是:

由于各种原因,我在父组件中运行查询,然后将数据作为道具传递给子组件:

家长

// Initialization, etc.
[...]

const {loading: loadingIndex, error: errorIndex, data: dataIndex, fetchMore: fetchMoreIndex} = useQuery(ARTICLE_QUERY.articles.indexArticles, {
    // Last 30 days
    variables: {
      live: live,
      limit: 10
    }
  });

  // Exception check
  if (errorIndex) {
    return <ErrorDb error={errorIndex} />
  }
  // DB fetching check
  if (loadingIndex) {
    return (
      <section className="index-articles">
        <h6>Index - Articles</h6>
        <aside className="articles__loading">
          <h6>Loading</h6>
        </aside>
      </section>
    );
  }

  const articles = dataIndex.queryArticleContents;

  return (
    <IndexArticles labels={props.labels} articles={articles} fetchMore={fetchMoreIndex} />
  );

孩子

// Initialization, etc.
[...]

let limit = 10; // My query hypothetically limiter
const IndexArticles = (props) => {
  useEffect(() => {
    // This is a getter method responsible to manage the ```fetchMore``` response
    getArticles(props.articles, props.fetchMore);
  });

return (
    <>
     // Component sections
    [...]

     // Load button
    {props.fetchMore &&
          <button className="articles__load" title={props.labels.index.title} tabIndex={40}>{props.labels.index.cta}</button>
        }
    </>
);

function getArticles(articles, fetchMore) {
  // Yes, I'm using jQuery with React. Just ignore it
  $('.articles__load').on('click tap', function(e) {
    e.preventDefault();

    $(this).addClass('hidden');
    $('.articles__loading').removeClass('hidden');

    fetchMore({
      variables: {
        // Cursor is being pointed to the last available element of the current collection
        lastLoaded: articles.length,
        limit: limit += 10
      },
      updateQuery: (prev, {fetchMoreResult, ...rest}) => {
        $('.articles__loading').addClass('hidden');
        $(this).removeClass('hidden');

        if (!fetchMoreResult) {
          return prev;
        }

        return {
          ...fetchMoreResult,
          queryArticleContents: [
            ...prev.queryArticleContents,
            ...fetchMoreResult.queryArticleContents
          ]
        }
      }
    });
  });
}

有没有人有这方面的经验或者以前经历过这种情况?

在此先感谢您的帮助

标签: reactjsmongodbgraphqlnext.jsapollo-client

解决方案


正如官方社区所建议的那样,我notifyOnNetworkStatusChange: true的查询选项中缺少我的配置,该选项负责更新组件并附加新数据。

通过以这种方式更改代码:

家长


const {
  loading: loadingIndex, 
  error: errorIndex, 
  data: dataIndex, 
  // Add networkStatus property too in order to use notifyOnNetworkStatusChange properly
  networkStatus: networkStatusIndex
  fetchMore: fetchMoreIndex} = useQuery(ARTICLE_QUERY.articles.indexArticles, {
    // Last 30 days
    variables: {
      live: live,
      limit: 10
    },
    // Important for component refreshing with new data
    notifyOnNetworkStatusChange: true 
  });

问题已解决。


推荐阅读