在查询组件之外显示 Apollo 客户端查询加载的最佳实践?

Posted

技术标签:

【中文标题】在查询组件之外显示 Apollo 客户端查询加载的最佳实践?【英文标题】:Best practice to show Apollo Client Query loading outside of Query Component? 【发布时间】:2019-11-02 17:36:25 【问题描述】:

我想在我的查询组件之外显示加载指示器。

现在我正在使用 redux,当我开始从 api 加载数据时,我设置了 redux state 属性,然后我用它来显示加载器组件。

如何使用 Apollo 客户端查询/突变实现相同的目标? 每个示例都显示了 Query 内部的加载道具,但如何在此 Query 之外显示加载器?

假设我有这样的事情:

<Header><Loader/></Header>
<Content><Query><List /></Query></Content>

但我不想用 Query 包装所有内容并执行以下操作:

<Query>
<Header><Loader/></Header>
<Content><List ></Content>
</Query>

这甚至可能吗? 加载时我应该在 Query 中更改 @client 缓存吗?

编辑:我想用 apollo-link-state 替换 redux,所以解决方案不应该使用 redux。

【问题讨论】:

【参考方案1】:

我建议使用react-apollo-hooks,它使 Apollo 的使用更加轻松有趣。

看看示例代码

import React from 'react';
import  useQuery  from 'react-apollo-hooks';
import get from 'lodash.get';
import SUBSCRIPTIONS_QUERY from './Subscriptions.graphql';
import s from './SubscriptionTable.scss';

const SubscriptionsTable = () => 
  const  data, loading, error  = useQuery(SUBSCRIPTIONS_QUERY);

  if (loading) return "Loading...";
  if (error) return `Error! $error.message`;

  return (
    <div className=s.SubscriptionTable>
      <div className=s.SubscriptionTable__Header>Email</div>
      get(data, 'subscriptions', []).map(subscription => (
        <div key=get(subscription, 'id') className=s.SubscriptionTable__Row>
          get(subscription, 'email')
        </div>
      ))
    </div>
  );
;

【讨论】:

虽然这看起来很有趣,但我认为它不会解决我的问题。如果我这样做: const data, loading, error = useQuery(SUBSCRIPTIONS_QUERY); const 数据:data1,加载:loading1,错误:error1 = useQuery(SUBSCRIPTIONS_QUERY);如果我然后以某种方式重新获取第一个,那么第二个可能不会显示加载? 这是方向,不是解决方案 @Lauri Apollo 基于查询和变量进行缓存。所以data1集永远不会上网。您需要部署 refetch 或使其成为 useLazyQuery。【参考方案2】:

首先,没有理由将你的加载状态放在 Redux 中,但如果你真的想出于某种原因你应该在组件挂载时将你的 redux 状态设置为loading: true,并在安装时将你的 redux 状态设置为loading: false组件中的加载不再正确。这就是我的意思:

import React from 'react';
import 
  useQuery,
  useEffect
 from 'react-apollo-hooks';
import get from 'lodash.get';
import SUBSCRIPTIONS_QUERY from './Subscriptions.graphql';
import s from './SubscriptionTable.scss';

const SubscriptionsTable = () => 
  const 
    data,
    loading,
    error
   = useQuery(SUBSCRIPTIONS_QUERY);

  useEffect(() => 
    // set loading: true in redux state 
    // as soon as component mounts
    // via action/reducer pattern
  , [])

  if (loading) 
    return "Loading..."
   else 
    // set loading: false in redux state 
    // when query no longer loading
    // via action/reducer pattern
  

  if (error) return `Error! $error.message`;

  return (<div>JSON.stringify(data)</div>);
;

【讨论】:

以上是关于在查询组件之外显示 Apollo 客户端查询加载的最佳实践?的主要内容,如果未能解决你的问题,请参考以下文章

Graphql,react-apollo如何在加载组件状态时将变量传递给查询

连接到多个组件时的 Apollo 客户端查询和数据存储

@client Apollo GQL 标签中断查询

为啥 WebStorm 在 Vue 组件或 .graphql 文件中的 apollo 对象内的 gql 查询中显示错误

如何在 apollo 客户端查询上全局设置 fetchPolicy?

通过 apollo 客户端测试使用查询和订阅的反应组件