如何修复graphql突变类型名称错误

时间:2018-10-12 19:55:56

标签: javascript graphql graphql-js apollo-client

我尝试使用apollo graphQl client进行GraphQ1突变。

当突变变量包含error 500个属性时(这显然在graphQl模式中不存在),这将产生一个___typename

要解决此问题,可以在graphQl客户端配置中设置addTypename: false

const graphqlClient = new ApolloClient({
  link: authLink.concat(httpLink),
  cache: new InMemoryCache({
    addTypename: false
  })
})

现在,突变几乎起作用了……

但是有一个新错误:You're using fragments in your queries, but either don't have the addTypename: true option set in Apollo Client, or you are trying to write a fragment to the store without the __typename. Please turn on the addTypename option and include __typename when writing fragments so that Apollo Client can accurately match fragments.

那么应如何配置graphQl客户端以处理突变?

现在我使用发现here的清理功能:

const removeTypename = (value) => {
  if (value === null || value === undefined) {
    return value;
  } else if (Array.isArray(value)) {
    return value.map(v => removeTypename(v));
  } else if (typeof value === 'object') {
    const newObj = {};
    Object.keys(value).forEach(key => {
      if (key !== '__typename') {
        newObj[key] = removeTypename(value[key]);
      }
    });
    return newObj;
  }
  return value;
};

但是感觉很hacky。有内置的graphql客户端吗?

2 个答案:

答案 0 :(得分:2)

因此,由于@Daniel Rearden的想法和this的评论,我使用了一个自定义的阿波罗链接从突变变量中删除类型名:

const omitTypename = (key, value) => {
  return key === '__typename' ? undefined : value
}

const omitTypenameLink = new ApolloLink((operation, forward) => {
  if (operation.variables) {
    operation.variables = JSON.parse(
      JSON.stringify(operation.variables),
      omitTypename
    )
  }
  return forward(operation)
})

然后将其与其他链接一起使用,例如:

const link = ApolloLink.from([authLink, omitTypenameLink, httpLink])
const cache = new InMemoryCache()

const graphqlClient = new ApolloClient({
  link,
  cache
})

答案 1 :(得分:1)

采用某些查询的值,然后将其插入变量作为变量是一种不典型的情况,因此要解决的问题并不容易。虽然您可以配置客户端实例以从结果中省略.Equals()字段,但是对象的__typename(以及其__typenameid)用作缓存键-如果它没有彻底破坏事物,则省略它会导致一些意外行为。

到目前为止,最好的方法是在将查询结果作为变量传递之前对其进行操作。我认为这样的方法应该可以解决问题:

_id

另一方面,除非您使用的是客户端数据(即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 } } ),否则很难想象会从服务器获取一些数据然后必须将这些数据馈送到服务器中的情况。突变。如果数据已经存在于服务器上,则应该为其传递一个ID并在服务器端检索它就足够了。如果您必须克服这些麻烦,则可能表明API本身需要更改。