简体   繁体   English

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

[英]What does Relay use to decide which outputFields to include in a mutation response?

I am creating my first React/Relay application by modifying the TODO example. 我通过修改TODO示例创建了我的第一个React / Relay应用程序。 I am to the point where I am adding my own mutation for an object Distributor that has a parameter bookCount. 我正在为一个具有参数bookCount的对象Distributor添加我自己的变异。 The mutation is called AddBook and simply increases book count by 1. At this point, the mutation executes without error, optimistically increases the bookCount by 1 correctly, but then reverts the model change when it receives the response from the server. 该变异称为AddBook,只是将书籍数量增加1.此时,变异执行时没有错误,乐观地将bookCount正确地增加1,但是当它从服务器接收到响应时恢复模型更改。 I believe this to be because the response from the server mysteriously does not contain any of my specified outputFields. 我相信这是因为来自服务器的响应神秘地不包含任何我指定的outputFields。

Here is my mutation: 这是我的突变:

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

It contains the field 'distributor' in outputFields but no 'distributor' data is included in the graphql response. 它包含outputFields中的字段“distributor”,但graphql响应中不包含“distributor”数据。

The graphql response is: graphql响应是:

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

I have verified that the mutateAndGetPayload function DOES get called but the distributor resolve function DOES NOT get called. 我已经验证了mutateAndGetPayload函数被调用但是分发器解析函数没有被调用。

I would have expected every field in outputFields to be included in the graphql response, and every resolve function within outputFields to be called to populate the appropriate parameters in the response but this is not the case 我希望outputFields中的每个字段都包含在graphql响应中,并调用outputFields中的每个resolve函数来填充响应中的相应参数,但事实并非如此

This is particularly confusing to me because the generated schema.json DOES include any outputFields that I specify in the AddBookPayload: 这对我来说尤其令人困惑,因为生成的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
    },

I was finally able to discover the answer to this question myself and the bug in the code so I will include it here for anyone else facing the same concern. 我终于能够自己发现这个问题的答案以及代码中的错误,所以我会把它包含在这里面对其他任何面临同样问题的人。

The first crucial thing to understand is the relationship between the FatQuery and the selectionSet. 要理解的第一个重要的事情是FatQuery和selectionSet之间的关系。 The FatQuery is used by the (web) client to understand what are the possible things that can change after the mutation in question is executed. (Web) 客户端使用FatQuery来了解在执行问题突变之后可能发生的变化。 The client will parse the fat query and its own internal state to see if there is any overlap. 客户端将解析胖查询及其自身的内部状态,以查看是否存在重叠。 If the FatQuery indicates that nothing in the mutation will change anything that the client currently cares about (exists in its internal store), then the client will use GraphQL to indicate that it does not want any data to be returned (if you use all of the default javascript libraries, this will be converted from no-data-returned to only-the-client-mutation-id). 如果FatQuery指示突变中的任何内容都不会改变客户端当前关心的任何内容(存在于其内部存储中),那么客户端将使用GraphQL来指示它不希望返回任何数据(如果您使用全部默认的javascript库,这将从no-data-returned转换为only-the-client-mutation-id)。 This is accomplished by means of the selectionSet. 这是通过selectionSet完成的。 You can view the selection set being requested in GraphQL by looking at the network call to the server in the browser window. 您可以通过查看浏览器窗口中对服务器的网络调用来查看GraphQL中请求的选择集。 In my case, that selection set was empty which was my first clue. 就我而言,那个选择集是空的,这是我的第一个线索。

So, long story short, the outputFields included in the mutation response are the intersection of all listed outputFields from the FatQuery and GraphQL client's internal state. 因此,长话短说,变异响应中包含的outputField是FatQuery和GraphQL客户端内部状态中所有列出的outputField的交集。

PS There is one other crucial factor that came into play here which is the specifying of the IDs that can be modified. PS此处还有另外一个关键因素,即指定可以修改的ID。 Every bit of data in GraphQL must have a globally unique id. GraphQL中的每一位数据都必须具有全局唯一ID。 In the TODO app example, that globally unique ID is create as a combination of the type name in question and the 'id' member variable of the type in question. 在TODO应用程序示例中,该全局唯一ID被创建为所讨论的类型名称和所讨论类型的“id”成员变量的组合。 In my case, since I had no 'id' member variable, some confusion ensued. 在我的情况下,因为我没有'id'成员变量,所以引起了一些混乱。 So, if like me, you are experimenting with using the TODO app as the basis of your experiments, do make sure that any type you create has a type-unique member variable named 'id'. 因此,如果像我一样,您正在尝试使用TODO应用程序作为实验的基础,请确保您创建的任何类型都具有名为“id”的类型唯一成员变量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM