问题描述
问题定义
在我目前正在进行的项目中,我们将 React 与 Apollo Client 结合使用。
对于我们所有的突变,我们的响应中有以下字段:
ok
errors {
field
messages
}
后端使用这些字段扩展所有突变,因此最好有一种好的、简短的方法将这些字段包含在前端的所有突变中,并且能够更改此“片段”未来。
因此,我有兴趣将所有突变中的这 4 行缩短为 1。
到目前为止我尝试过的:
我曾尝试查看 Apollo fragments,但它们似乎需要字段为 on
或“相关于”的类型,例如。
fragment NameParts on Person {
firstName
lastName
}
这里,框架 NameParts
是使用 Person
创建的。但是,我对扩展所有突变感兴趣。
如果我能像这样制作一个通用片段就好了:
fragment OkAndErrors {
ok
errors {
field
messages
}
}
这似乎是不可能的。
我也试过制作一个字符串,然后像这样将它导入到我的突变中:
export const OK_AND_ERRORS: string = `
ok
errors {
field
messages
}
`;
import { gql } from "apollo-boost";
import { OK_AND_ERRORS } from "./OK_AND_ERRORS";
export const CREATE_API = gql`
mutation CreateApi($newApi: ApiCreateGenericType!) {
createDrugapi(newDrugapi: $newDrugapi) {
${OK_AND_ERRORS}
(...rest of mutation is omitted for brevity)
}
}
`;
再一次,它不起作用。
我不确定是否可以通过字符串或 JSON 巧妙地使用 gql
函数?
还有 inline fragments 但我怀疑它是否可以用于我需要的,并且 Apollo 中内联片段的文档很少。
本质上:有没有一种聪明的方法来扩展 Apollo 突变?是否存在通用片段?
解决方法
首先,片段不限于 Apollo,而是常规 GraphQL 查询的一部分。 GraphQL 站点本身实际上对它们有很好的解释:https://graphql.org/learn/queries/#fragments
本质上,我们可以将片段放在任何查询上以提取数据依赖关系,但它们对于使用 on X
类型条件匹配类型也很有用。
在您的情况下,您是说每个突变都返回一种具有公共 errors
字段的结果类型。这告诉我您可能已经有一个 MutationError
类型。但是,这些都具有 MutationResult
字段的 errors
类型都应该实现接口(如果它们还没有实现)。
接口是模式语言中的一个很好的工具,用于明确定义实现它的类型必须始终包含一组特定的字段,在本例中为 errors
字段。这意味着我们会像这样写我们的结果:
interface MutationResult {
errors: [MutationError!]
}
type ExampleMutationResult implements MutationResult {
ok: Boolean
errors: [MutationError!]
}
type UserMutationResult implements MutationResult {
user: User
errors: [MutationError!]
}
正如您在上面看到的,MutationResult
接口现在由几个结果实现,这使我可以编写一个可重用的片段,该片段可以应用于实现它的任何类型,例如
fragment MutationResultErrors on MutationResult {
errors {
field
messages
}
}
然后我可以开始使用我定义的所有突变查询。这在 GraphQL 中更具可预测性和预期,而不是在查询中进行一些客户端文档转换、字符串插值或类似操作,因为它将被烘焙到您的架构中。
旁注:我还要说的是,我发现人们已经开始将他们的突变分为“错误”和“结果”,并做出某种union 或 interface 来区分两者。但通常他们会通过消息实现通用错误。重要的是要说不携带任何关系数据的错误实际上已经被嵌入到 GraphQL 中:https://spec.graphql.org/June2018/#sec-Errors