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

Ove*_*Tim 2 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 {};
  },
});
Run Code Online (Sandbox Code Playgroud)

它包含outputFields中的字段"distributor",但graphql响应中不包含"distributor"数据.

graphql响应是:

{
  "data": {
  "addBook": {
    "clientMutationId": "0"
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

我已经验证了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
    },
Run Code Online (Sandbox Code Playgroud)

Ove*_*Tim 9

我终于能够自己发现这个问题的答案以及代码中的错误,所以我会把它包含在这里面对其他任何面临同样问题的人.

要理解的第一个重要的事情是FatQuery和selectionSet之间的关系.FatQuery由(Web)客户端使用了解在执行问题突变后可能发生的变化.客户端将解析胖查询及其自身的内部状态,以查看是否存在重叠.如果FatQuery指示突变中的任何内容都不会改变客户端当前关心的任何内容(存在于其内部存储中),那么客户端将使用GraphQL来指示它不希望返回任何数据(如果您使用全部数据)默认的javascript库,这将从no-data-returned转换为only-the-client-mutation-id).这是通过selectionSet完成的.您可以通过查看浏览器窗口中对服务器的网络调用来查看GraphQL中请求的选择集.就我而言,那个选择集是空的,这是我的第一个线索.

因此,长话短说,变异响应中包含的outputField是FatQuery和GraphQL客户端内部状态中所有列出的outputField的交集.

PS此处还有另外一个关键因素,即指定可以修改的ID.GraphQL中的每一位数据都必须具有全局唯一ID.在TODO应用程序示例中,该全局唯一ID被创建为所讨论的类型名称和所讨论类型的"id"成员变量的组合.在我的情况下,因为我没有'id'成员变量,所以引起了一些混乱.因此,如果像我一样,您正在尝试使用TODO应用程序作为实验的基础,请确保您创建的任何类型都具有名为"id"的类型唯一成员变量.