在 Relay 中,节点接口和全局 ID 规范扮演什么角色? [英] In Relay, what role do the node interface and the global ID spec play?

查看:16
本文介绍了在 Relay 中,节点接口和全局 ID 规范扮演什么角色?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我从 relay-starter-kit 开始,还按照自己的方式阅读了 Relay 和 GraphQL 文档.但也有不少地方是无法解释和神秘的.

I started out with the relay-starter-kit and also worked my way through the Relay and GraphQL documentation. But there are quite a few areas that are unexplained and mysterious.

说真的,我到处都阅读了很多关于所有这些事情的文档,但找不到对以下问题的任何令人满意的解释:

Seriously I read a lot of documentations everywhere about all these things but couldn't find any satisfying explanations for the following questions:

这是干什么用的?我写了日志,但它甚至从来没有被调用过:

What is this for? I put logging but it never even gets called at all:

var {nodeInterface, nodeField} = nodeDefinitions(
  (globalId) => {
    var {type, id} = fromGlobalId(globalId);
    if (type === 'User') {
      return getUser(id);
    } else if (type === 'Widget') {
      return getWidget(id);
    } else {
      return null;
    }
  },
  (obj) => {
    if (obj instanceof User) {
      return userType;
    } else if (obj instanceof Widget) {
      return widgetType;
    } else {
      return null;
    }
  }
);

这个的实际效果是什么:

And what is the actual effect of this:

interfaces: [nodeInterface],

也许与此有关,这里的 node 字段是做什么的:

Maybe related to that, what does the node field here do:

var queryType = new GraphQLObjectType({
  name: 'Query',
  fields: () => ({
    node: nodeField,
    // Add your own root fields here
    viewer: {
      type: userType,
      resolve: () => getViewer(),
    },
  }),
});

id 字段有什么神奇之处?globalIdField 有什么用?

And what is the magic around the id field? What is globalIdField for?

我的数据库中有一个 id 并认为我可以在我的 GraphQL 对象中使用它:

I have an id in my database and thought I could use it in my GraphQL objects:

代替:

id: globalIdField('User'),

我想使用我的数据库 ID:

I want to use my database id:

id: {
  type: GraphQLID,
  description: 'The identifier'
},

但是如果我这样做,我会在浏览器中收到一个错误消息,提示 RelayQueryWriter: 找不到记录 '1' 的类型名称.

But if I do that I get an error in the browser saying RelayQueryWriter: Could not find a type name for record '1'.

我可以通过将 __typename 添加到我的组件容器 Relay Query 来消除该错误,但这似乎完全错误.

I can get rid of that error by adding __typename to my component containers Relay Query but that seems all wrong.

如果你能在这里给出一些更深入的内幕和更好的解释并增强官方文档,那就太好了.

It would be great if you could give some deeper insides and a better explanation here and enhance the official documentation.

谢谢

推荐答案

Node 根字段,结合全局唯一 ID,在 Relay 需要refetch 一个物体.当您调用 this.props.relay.forceFetch() 或当您将字段添加到查询的全局 ID 已被部分提取的对象的查询时,会发生重新提取.

The Node root field, in combination with globally unique IDs, comes into play when Relay needs to refetch an object. Refetching occurs when you call this.props.relay.forceFetch() or when you add fields to the query for an object whose global ID is known because it has already been partially fetched.

在这种情况下,Relay 会短路常规查询并使用其全局 ID 和 node 根调用直接执行对对象的查询.

In cases like these, Relay will short circuit the regular query and execute a query for the object(s) directly using its global ID and the node root call.

示例:

假设第一次解析此查询时 $showCommentsfalse.

Assume that $showComments was false when this query was first resolved.

query {
  viewer {
    stories(first: 10) {
      edges {
        node {
          id,
          comments(first: 10) @include(if: $showComments) { 
            author, 
            commentText 
          }
          text,
        }
      }
    }
  }
}

这将导致对一些 ID 已知的故事的 idtext 进行提取.

This will have caused a fetch for id and text for some number of stories, whose IDs are now known.

想象一下,在未来的某个时间,变量 $showComments 变成了 true.Relay 将使用 node 根字段仅重新获取它需要的数据.

Imagine that at some future time, the variable $showComments became true. Relay will refetch only the data it needs using the node root field.

query {
  node(id: "ABC123") { 
    fragment on Story { comments(first: 10) { author, commentText } }
  }
  node(id: "DEF456") { 
    fragment on Story { comments(first: 10) { author, commentText } }
  }
  node(id: "GHI789") { 
    fragment on Story { comments(first: 10) { author, commentText } }
  }
  ...
}

这取决于几个部分:

  1. 每个对象都必须有一个全局唯一的 ID,或者由类型/ID 对标识(globalIdField 助手会执行此操作并生成一个 base64 编码的字符串).
  2. 服务器必须知道如何从全局唯一 ID 解析对象,反之亦然.这就是 nodeDefinitions 的用途.
  3. 任何希望使用该系统重新获取的对象都必须实现nodeInterface.
  1. Each object must have a globally unique ID, or be identified by a type/ID pair (the globalIdField helper does this and produces a base64 encoded string).
  2. The server must know how to resolve an object from a globally unique ID, and vice versa. This is what the nodeDefinitions are for.
  3. Any object that hopes to be refetchable using this system must implement the nodeInterface.

另见:https://relay.dev/docs/guides/graphql-server-specification/#object-identification

这篇关于在 Relay 中,节点接口和全局 ID 规范扮演什么角色?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆