React/Apollo - 不同组件中的类似查询?

React/Apollo - Similar Queries in different Component?

我正在寻求有关使用 Apollo、React 和 Meteor 的最佳实践的帮助。

我将 Meteor.user() 模型链接到 Apollo 中的架构,现在我可以访问它,这要归功于查询组件。我有一个看起来像这样的查询:

gql`
  query User {
    user {
      _id,
      email
    }
  }
`

它完成了工作,解析器直接给出了电子邮件地址。但是我在不同的地方需要它,对于我需要它的每个组件,我正在制作另一个 < Query > 具有相同查询的组件,我将粘贴从一个文件复制到另一个。在我看来,如果我的许多组件一次又一次地查询相同的东西,我就失去了所有意义。但是我没能找到这个 "DRY" 问题的解决方案。目前还没有太多示例,包括来自 React apollo 的查询组件,所以如果有人可以帮助我,我将不胜感激。

您可以在查询中使用 cache-onlycache-first 策略。

Docs

默认情况下,Apollo 客户端使用 fetchPolicycache-first。这意味着如果查询结果已经在缓存中,它将从那里获取并且不会发出网络请求。这使您可以跨多个 Query 组件使用相同的查询,而不必担心一遍又一遍地向您的服务器发出相同的请求。

如果您想覆盖此默认行为,您可以为特定查询组件指定 fetchPolicy -- 例如,您可能希望始终从服务器获取新数据,在这种情况下您将使用network-only 或者 cache-and-network。有关详细信息,请参阅 the docs

注意:一个常见的"gotcha"是缓存使用id(或_id)字段来规范化缓存结果。这意味着您的查询必须包含 id 字段(或提供 dataIdFromObject 的自定义实现)才能看到预期的行为。请参阅此 page 了解更多详细信息。

就保持干爽而言,将查询存储在一个或多个单独的模块中然后根据需要导入它们是一种常见的做法。所以你可以有一个像这样的 queries.js 文件:

import gql from 'graphql-tag'

export const USER_QUERY = gql`
  query User {
    user {
      _id,
      email
    }
  }
`

graphql-tag 附带一个加载程序,如果您使用的是 Webpack,则可以让您直接从 .graphql/.gql 文件导入查询。查看食谱 here. There's also a babel plugin for doing effectively the same thing (checkout it out here)。这些方法中的任何一种都应该减少代码中的冗余。

编辑:正如@camba1 的回答中所指出的,片段也可以用来干掉你的查询:

query User {
  user {
    ...userFields
  }
}

fragment userFields on User {
  _id,
  email,
}

避免到处复制粘贴查询代码可能有用的另一件事是使用查询片段。

例如:

# Query that contains a fragment
query myQuery1($_key: ID!) {
  myQuery1(_key: $_key) {
    field1,
    ...myFragmentFields
    }
  }

# Fragment to be used in queries
fragment myFragmentFields on myQueryType {
    _key,
    name,
    formula,
    type
  }

这里是 documentation: