Relay使用什么来决定在变异响应中包含哪些outputField?

时间:2015-09-16 00:06:39

标签: javascript relayjs

我通过修改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
    },

1 个答案:

答案 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'的类型唯一成员变量。