在 Relay 中,node interface 和 global ID spec 起什么作用?
In Relay, what role do the node interface and the global ID spec play?
我从 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
添加到我的组件容器中继查询来消除该错误,但这似乎完全错误。
如果你能在这里给出更深入的内部和更好的解释并完善官方文档,那就太好了。
谢谢
当 Relay 需要 refetch 对象时,Node
根字段与全局唯一 ID 结合使用。当您调用 this.props.relay.forceFetch()
或将字段添加到全局 ID 已知的对象的查询中时,会发生重新提取,因为它已被部分提取。
在这种情况下,中继将缩短常规查询并直接使用其全局 ID 和 node
根调用执行对象查询。
示例:
假设首次解析此查询时 $showComments
是 false
。
query {
viewer {
stories(first: 10) {
edges {
node {
id,
comments(first: 10) @include(if: $showComments) {
author,
commentText
}
text,
}
}
}
}
}
这将导致提取 id
和 text
一些故事,其 ID 现在已知。
想象一下,在未来的某个时间,变量 $showComments
变成了 true
。中继将使用 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 } }
}
...
}
这要看几块:
- 每个对象必须有一个全局唯一的 ID,或者由 type/ID 对标识(
globalIdField
助手执行此操作并生成 base64 编码的字符串)。
- 服务器必须知道如何从全局唯一 ID 解析对象,反之亦然。这就是
nodeDefinitions
的用途。
- 任何希望使用此系统可重新获取的对象都必须实现
nodeInterface
.
另请参阅:https://relay.dev/docs/guides/graphql-server-specification/#object-identification
我从 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
添加到我的组件容器中继查询来消除该错误,但这似乎完全错误。
如果你能在这里给出更深入的内部和更好的解释并完善官方文档,那就太好了。
谢谢
当 Relay 需要 refetch 对象时,Node
根字段与全局唯一 ID 结合使用。当您调用 this.props.relay.forceFetch()
或将字段添加到全局 ID 已知的对象的查询中时,会发生重新提取,因为它已被部分提取。
在这种情况下,中继将缩短常规查询并直接使用其全局 ID 和 node
根调用执行对象查询。
示例:
假设首次解析此查询时 $showComments
是 false
。
query {
viewer {
stories(first: 10) {
edges {
node {
id,
comments(first: 10) @include(if: $showComments) {
author,
commentText
}
text,
}
}
}
}
}
这将导致提取 id
和 text
一些故事,其 ID 现在已知。
想象一下,在未来的某个时间,变量 $showComments
变成了 true
。中继将使用 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 } }
}
...
}
这要看几块:
- 每个对象必须有一个全局唯一的 ID,或者由 type/ID 对标识(
globalIdField
助手执行此操作并生成 base64 编码的字符串)。 - 服务器必须知道如何从全局唯一 ID 解析对象,反之亦然。这就是
nodeDefinitions
的用途。 - 任何希望使用此系统可重新获取的对象都必须实现
nodeInterface
.
另请参阅:https://relay.dev/docs/guides/graphql-server-specification/#object-identification