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

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

问题描述

我在流星/反应/阿波罗(带升压)项目中遇到问题.当我从服务器查询数据时,它将__typename添加到查询中的每个对象和子对象,但就我的情况而言,这会造成一个主要问题,因为我通常会重复使用这些数据将其发送给其他突变.现在,另一个突变告诉我有一个错误,因为在我的graphql模式中未定义__typename字段.

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 :

  • 在客户端手动过滤
  • 将中间件添加到阿波罗
  • 将__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天全站免登陆