10

Article我的架构中有一个类型:

type Article {
  id: ID!
  updated: DateTime
  headline: String
  subline: String
}

对于它的更新,updateArticle(id: ID!, article: ArticleInput!)突变使用了相应的输入类型:

input ArticleInput {
  headline: String
  subline: String
}

突变本身如下所示:

mutation updateArticle($id: ID!, $article: ArticleInput!) {
  updateArticle(id: $id, article: $article) {
    id
    updated
    headline
    subline
  }
}

文章总是作为一个整体保存(而不是一个一个字段),所以当我将一篇文章传递给我之前获取的那个突变时,它会抛出像Unknown field. In field "updated",Unknown field. In field "__typename"Unknown field. In field "id". 这些有根本原因,这些字段没有在输入类型上定义。

根据规范,这是正确的行为:

(...) 此无序映射不应包含名称未由此输入对象类型的字段定义的任何条目,否则应引发错误。

现在我的问题是处理这些情况的好方法是什么。我应该在我的应用代码中列出输入类型允许的所有属性吗?

如果可能的话,我想避免这种情况,并且可能有一个实用函数为我切掉它们,它知道输入类型。但是,由于客户端不知道架构,这必须发生在服务器端。因此,不必要的属性将被转移到那里,我想这就是为什么它们不应该首先被转移的原因。

有没有比维护属性列表更好的方法?

我正在使用apollo-client,react-apollographql-server-express.

4

2 回答 2

10

您可以使用片段进行查询,其中包括数据的所有可变字段。过滤器实用程序可以使用该片段在突变发生之前删除所有不需要的数据。

要点是:

const ArticleMutableFragment = gql`
fragment ArticleMutable on Article {
  headline
  subline
  publishing {
    published
    time
  }
}
`

const ArticleFragment = gql`
fragment Article on Article {
  ...ArticleMutable
  id
  created
  updated
}
${ArticleMutableFragment}
`;

const query = gql`
query Article($id: ID!) {
  article(id: $id) {
    ...Article
  }
}
${ArticleFragment}
`;

const articleUpdateMutation = gql`
mutation updateArticle($id: ID!, $article: ArticleInput!) {
  updateArticle(id: $id, article: $article) {
    ...Article
  }
}
${ArticleFragment}
`;

...

import filterGraphQlFragment from 'graphql-filter-fragment';

...

graphql(articleUpdateMutation, {
  props: ({mutate}) => ({
    onArticleUpdate: (id, article) =>
      // Filter for properties the input type knows about
      mutate({variables: {id, article: filterGraphQlFragment(ArticleMutableFragment, article)}})
  })
})

...

ArticleMutable片段现在也可以用于创建新文章。

于 2017-03-06T17:54:50.647 回答
0

我个人也有同样的想法,并且更早地采用了@amann 的方法,但一段时间后,在输入类型上使用查询片段的概念缺陷变得明显。您将无法选择(相应的)对象类型中不存在的输入类型字段 - 甚至有吗?

目前我正在通过typesafe-joi模式描述我的输入数据,并使用它的stripUnknown选项来过滤掉我的表单数据。

无效数据永远不会离开表单,因此可以静态输入有效数据。

从某种意义上说,创建 joi 模式与定义“输入片段”的活动相同,因此不会发生代码重复,并且您的代码可以是类型安全的。

于 2019-02-22T13:09:05.277 回答