Apollo boost - 查询中的 __typename 防止新的突变 [英] Apollo boost - __typename in query prevent new mutation

查看:31
本文介绍了Apollo boost - 查询中的 __typename 防止新的突变的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的meteor/react/apollo (with boost) 项目有问题.当我从服务器查询数据时,它将 __typename 添加到我查询中的每个对象和子对象,但在我的情况下,它会产生一个主要问题,因为我通常会重用这些数据将它们发送到其他突变.现在另一个突变告诉我有一个错误,因为 __typename 字段没有在我的 graphql 模式中定义.

I have a problem in my meteor/react/apollo (with boost) project. When I query data from the server, it adds __typename to every object and subobject in my query but it my case it creates a major issue as I normally reuse these data to send them to other mutation. Now the other mutation tell me there is an error because the __typename field is not defined in my graphql schema.

我试图通过将 addTypename: false 字段添加到我的 apollo 客户端来修复,但它没有改变任何东西(注意我使用的是 apollo boost,这可能就是它不工作的原因):

I tried to fix by adding the addTypename: false field to my apollo client but it didn't change anything (note I am using apollo boost, that may be why it is not sworking) :

const client = new ApolloClient({
    uri: Meteor.absoluteUrl('graphql'),
    addTypename: false,
    request: operation =>
        operation.setContext(() => ({
            headers: {
                authorization: Accounts._storedLoginToken()
            }
        }))
})

此外,即使它有效,它似乎也不是很优化.在我看来,将字段添加到查询结果中似乎很成问题,我很惊讶没有在网上找到任何明确的解决方案.一些建议的解决方案,其中:

Also it seems than even if it worked it is not very optimized. It seems to me very problematic that a field is added to the query results and I am surprised not to find any clear solution online. Some proposed solution where :

  • 在客户端手动过滤
  • 向 apollo 添加中间件
  • 将 __typename 字段添加到我的所有架构中...

但它们似乎都不符合阿波罗假设为查询带来的简单性".我希望提供一个更简单、更合乎逻辑的解决方案,但到目前为止,找不到任何解决方案.

but none of them seem to fit the 'simplcity' apollo is suppose to bring for queries. I hope there is a simpler, more logical solution provided, but so far, could not find any.

推荐答案

即使使用 apollo-client 而不是 apollo-boost,你也不应该设置 addTypename 为 false,除非您有令人信服的理由这样做.__typename 字段由 InMemoryCache 使用来规范化您的查询结果,因此省略它可能会导致缓存出现意外行为.

Even if using apollo-client and not apollo-boost, you shouldn't set addTypename to false unless you have a compelling reason to do so. The __typename field is used by the InMemoryCache to normalize your query results, so omitting it will likely lead to unexpected behavior around caching.

不幸的是,这个问题没有灵丹妙药".请求查询然后使用该查询的数据作为其他查询的变量可能会被解释为滥用 API.查询返回的 Type 和用作参数的 Input Type 是完全不同的东西,即使作为 Javascript 对象,它们共享一个或多个字段.就像您不能在架构中互换使用类型和输入类型一样,也不应该期望它们可以在客户端互换使用.

Unfortunately, there is no "silver bullet" to this problem. Requesting a query and then using that query's data as the variable to some other query could be construed as misusing the API. The Type returned by a query and the Input Type used as an argument are completely different things, even if as Javascript objects they share one or more fields. Just like you can't use types and input types interchangeably within a schema, there shouldn't be an expectation that they can be used interchangeably client-side.

这也意味着,如果您发现自己处于这种情况,您可能需要重新审视一下您的架构设计.毕竟,如果数据已经存在于服务器上,那么为它传入一个 id 并在服务器端检索它应该就足够了,而不必传入整个对象.

That also means that if you're finding yourself in this situation, you may want to take a second look at your schema design. After all, if the data exists on the server already, it should be sufficient to pass in an id for it and retrieve it server-side, and not have to pass in the entire object.

如果您使用某个查询来填充一个或多个输入,然后在突变中使用这些输入的值,那么您大概已经将初始查询数据转换为组件状态,然后在您的突变中使用它.在这种情况下,__typename 或任何其他不可编辑的字段可能首先不应该作为组件状态的一部分包含在内.

If you're using some query to populate one or more inputs and then using the value of those inputs inside a mutation, then you're presumably already turning the initial query data into component state and then using that in your mutation. In that scenario, __typename or any other non-editable fields probably shouldn't be included as part of component state in the first place.

在一天结束时,进行此类操作有望成为例外,而不是规则.我会创建某种辅助函数来清理"您的输入并继续前进.

At the end of day, doing these sort of manipulations will hopefully be the exception, and not the rule. I would create some kind of helper function to "sanitize" your input and move on.

function stripTypenames (value) {
    if (Array.isArray(value)) {
        return value.map(stripTypenames)
    } else if (value !== null && typeof(value) === "object") {
      const newObject = {}
      for (const property in value) {
          if (property !== '__typename') {
            newObject[property] = stripTypenames(value[property])
          }
      }
      return newObject
    } else {
      return value
    }
}

这篇关于Apollo boost - 查询中的 __typename 防止新的突变的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆