我通过修改TODO示例创建了我的第一个React / Relay应用程序。我正在为一个具有参数bookCount的对象Distributor添加我自己的变异。该变异称为AddBook,只是将书籍数量增加1.此时,变异执行时没有错误,乐观地将bookCount正确地增加1,但是当它从服务器接收到响应时恢复模型更改。我相信这是因为来自服务器的响应神秘地不包含我指定的任何outputFields。
这是我的突变:
var GraphQLAddBookMutation = mutationWithClientMutationId({
name: 'AddBook',
inputFields: {
},
outputFields: {
distributor: {
type: GraphQlDistributor,
resolve: () => getDistributor(),
},
},
mutateAndGetPayload: () => {
console.log("Trying to mutate.");
addBook();
return {};
},
});
它包含字段'经销商'在outputFields但没有'经销商'数据包含在graphql响应中。
graphql响应是:
{
"data": {
"addBook": {
"clientMutationId": "0"
}
}
}
我已经验证了mutateAndGetPayload函数被调用但是分发器解析函数没有被调用。
我原本希望outputFields中的每个字段都包含在graphql响应中,并调用outputFields中的每个resolve函数来填充响应中的相应参数,但事实并非如此
这对我来说特别困惑,因为生成的schema.json包含我在AddBookPayload中指定的任何outputField:
{
"kind": "OBJECT",
"name": "AddBookPayload",
"description": null,
"fields": [
{
"name": "distributor",
"description": null,
"args": [],
"type": {
"kind": "OBJECT",
"name": "Distributor",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "clientMutationId",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [],
"enumValues": null,
"possibleTypes": null
},
答案 0 :(得分:9)
我终于能够自己发现这个问题的答案以及代码中的错误,所以我会把它包含在其他面临同样问题的人中。
首先要理解的是FatQuery和selectionSet之间的关系。 (web)客户端使用FatQuery来了解在执行问题突变后可能发生的变化。客户端将解析胖查询及其自身的内部状态,以查看是否存在重叠。如果FatQuery指示突变中的任何内容都不会改变客户端当前关心的任何内容(存在于其内部存储中),那么客户端将使用GraphQL来指示它不希望返回任何数据(如果您使用全部默认的javascript库,这将从no-data-returned转换为only-the-client-mutation-id)。这是通过selectionSet完成的。您可以通过查看浏览器窗口中对服务器的网络调用来查看GraphQL中请求的选择集。就我而言,那个选择集是空的,这是我的第一个线索。
因此,长话短说,变异响应中包含的outputField是FatQuery和GraphQL客户端内部状态中所有列出的outputField的交集。
P.S。这里还有另外一个关键因素,即指定可以修改的ID。 GraphQL中的每一位数据都必须具有全局唯一ID。在TODO应用示例中,该全局唯一ID会被创建为相关类型名称和“ID”的组合。有问题类型的成员变量。在我的情况下,因为我没有' id'成员变量,随之而来的是一些混乱。因此,如果像我一样,您正在尝试使用TODO应用作为实验的基础,请确保您创建的任何类型都有一个名为' id'的类型唯一成员变量。