在Relay中,节点接口和全局ID规范扮演什么角色?

时间:2015-10-28 19:27:42

标签: reactjs graphql relayjs graphql-js

我从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;
    }
  }
);

这实际效果如何:

interfaces: [nodeInterface],

可能与此相关,此处node字段的作用是什么:

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

id字段周围的魔力是什么?什么是globalIdField

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

而不是:

id: globalIdField('User'),

我想使用我的数据库ID:

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

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

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

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

谢谢

1 个答案:

答案 0 :(得分:54)

当Relay需要重新一个对象时,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,
        }
      }
    }
  }
}

这会导致某些故事的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 } }
  }
  ...
}

这取决于几件:

  1. 每个对象必须具有全局唯一ID,或者由类型/ ID对标识(globalIdField帮助程序执行此操作并生成base64编码的字符串。)
  2. 服务器必须知道如何从全局唯一ID中解析对象,反之亦然。这就是nodeDefinitions的用途。
  3. 任何希望使用此系统反映的对象都必须实现nodeInterface
  4. 另请参阅:https://facebook.github.io/relay/docs/graphql-object-identification.html#content