在Relay中,节点接口和全局ID规范起什么作用?

Chr*_*ine 51 reactjs graphql graphql-js relayjs

我开始使用它,relay-starter-kit并通过Relay和GraphQL文档工作.但是有很多领域是无法解释和神秘的.

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

这个是来做什么的?我把日志记录但它甚至根本没有被调用:

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;
    }
  }
);
Run Code Online (Sandbox Code Playgroud)

这个的实际效果是什么:

interfaces: [nodeInterface],
Run Code Online (Sandbox Code Playgroud)

也许与此相关,node这里的领域是做什么的:

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

这个id领域的魔力是什么?什么是globalIdField

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

代替:

id: globalIdField('User'),
Run Code Online (Sandbox Code Playgroud)

我想使用我的数据库ID:

id: {
  type: GraphQLID,
  description: 'The identifier'
},
Run Code Online (Sandbox Code Playgroud)

但如果我这样做,我会在浏览器中收到错误消息RelayQueryWriter: Could not find a type name for record '1'.

我可以通过添加__typename到我的组件容器中继查询来摆脱该错误,但这似乎都是错误的.

如果你能在这里提供一些更深入的内容和更好的解释并增强官方文档,那将是很棒的.

谢谢

ste*_*her 54

Node根领域,在全球唯一的ID组合,进场时,继电器需要重新获取的对象.当您调用this.props.relay.forceFetch()或为全局ID已知因为已部分获取的对象的查询添加字段时,会发生重新获取.

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

示例:

假设$showCommentsfalse,当该查询首次解决.

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

这将导致一些故事的获取idtext一些故事,其ID现在已知.

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

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 } }
  }
  ...
}
Run Code Online (Sandbox Code Playgroud)

这取决于几件:

  1. 每个对象必须具有全局唯一ID,或者由类型/ ID对标识(globalIdField帮助程序执行此操作并生成base64编码的字符串).
  2. 服务器必须知道如何从全局唯一ID解析对象,反之亦然.这就是它nodeDefinitions的用途.
  3. 任何希望使用此系统可以反映的对象都必须实现nodeInterface.

另见:https://facebook.github.io/relay/docs/graphql-object-identification.html#content

  • 关于`fromGlobalId`和`toGlobalId`,或许可以补充一点这个答案?以及它们如何促进任何对象类型的重新获取?阅读https://github.com/graphql/graphql-relay-js/blob/master/src/node/node.js以及该回购中的其他文件对我帮助很大,但将这些东西提炼成文字会让我节省很多时间 (3认同)
  • 希望这很快就会进入教程.我也对此感到困惑了很长一段时间,直到我最终完成所有工作并将各个部分组合在一起. (2认同)