2

我正在通过修改 TODO 示例来创建我的第一个 React/Relay 应用程序。我已经到了为具有参数 bookCount 的对象分发器添加自己的突变的地步。变异被称为 AddBook 并且只是将书籍计数增加 1。此时,变异执行没有错误,乐观地将 bookCount 正确地增加 1,但是当它收到来自服务器的响应时恢复模型更改。我相信这是因为来自服务器的响应神秘地不包含我指定的任何输出字段。

这是我的突变:

var GraphQLAddBookMutation = mutationWithClientMutationId({
  name: 'AddBook',
  inputFields: {
  },
  outputFields: {
    distributor: {
      type: GraphQlDistributor,
      resolve: () => getDistributor(),
    },
  },
  mutateAndGetPayload: () => {
    console.log("Trying to mutate.");
    addBook();
    return {};
  },
});

它在 outputFields 中包含字段“distributor”,但 graphql 响应中不包含“distributor”数据。

graphql 响应是:

{
  "data": {
  "addBook": {
    "clientMutationId": "0"
    }
  }
}

我已经验证了 mutateAndGetPayload 函数会被调用,但分发器解析函数不会被调用。

我本来希望 outputFields 中的每个字段都包含在 graphql 响应中,并且 outputFields 中的每个解析函数都被调用以填充响应中的适当参数,但事实并非如此

这让我特别困惑,因为生成的 schema.json 确实包含我在 AddBookPayload 中指定的任何 outputFields:

{
      "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
    },
4

1 回答 1

9

我终于能够自己找到这个问题的答案以及代码中的错误,因此我将把它包含在这里,以供其他面临同样问题的人使用。

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

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

PS 这里还有另一个关键因素是指定可以修改的 ID。GraphQL 中的每一位数据都必须有一个全局唯一的 id。在 TODO 应用程序示例中,该全局唯一 ID 是作为相关类型名称和相关类型的“id”成员变量的组合创建的。就我而言,由于我没有“id”成员变量,因此出现了一些混乱。因此,如果您像我一样尝试使用 TODO 应用程序作为实验的基础,请确保您创建的任何类型都有一个名为“id”的类型唯一成员变量。

于 2015-09-17T21:50:55.357 回答