片段不能在此处传播,因为 "X" 类型的对象永远不会是 "Y" 类型的对象
Fragment cannot be spread here as objects of type "X" can never be of type "Y"
在这种情况下,类型 "X" 是 Application
,类型 "Y" 是类型 "Node" - 我明白了 为什么会这样,但我对 Relay 的理解不足以理解如何修复它。中继生成的查询是
query {
node(id: $some_id) {
...F0
}
}
fragment F0 on Application {
...
}
我的架构看起来像
query {
application {
/* kind of a generic endpoint for fetching lists, etc */
invites(token: $token) {
name
}
}
viewer { /* the current user */ }
}
我正在尝试从会话外部获取特定邀请(viewer
是 null
)。
我试过了
const application = Relay.QL`query { application }`
...
<Route ... queries={{ application }}/>
...
Relay.createContainer(Component, {
initialValues: { token: null },
fragments: {
application: () => {
fragment on Application {
invites(token: $token) {
...
}
}
}
}
})
这给了我错误
片段 "F0" 不能在这里传播,因为类型 "Node" 的对象永远不能是类型 "Application" - 或者类似的东西。
我有点困惑,因为如果我要编写原始查询并 运行 直接通过 GraphQL
query {
application {
invites(token: "asdasdasd") {
edges {
node {
name
}
}
}
}
}
它给了我想要的东西...
在后端,我的图表定义如下
export const Application = new GraphQLObjectType({
name: 'Application',
fields: () => ({
id: {
type: GraphQLString,
resolve: () => 'APPLICATION_ID'
},
invites: {
type: InviteConnectionType,
args: connectionArgs,
resolve: (application, args) => {
...
}
}
})
})
export default new GraphQLSchema({
query: new GraphQLObjectType({
name: 'query',
fields: {
node: nodeField,
application: {
type: Application,
resolve: (root, args, ctx) => {
return Promise.resolve({})
}
}
}
})
我一直在看 this and some issues on the Relay github 这样的问题,但我不清楚我应该如何实施 nodeInterface
。
编辑:当前nodeInterface
代码的短-长是
export const {
nodeInterface,
nodeField
} = nodeDefinitions(
(globalId) => {
const { type, id } = fromGlobalId(globalId)
return db[type].findById(id)
},
(obj) => {
const name = obj.$modelOptions.name.singular
return types[name]
}
)
应用程序不是数据库模型,但是,它只是一个用于获取数据的通用接口。我已经尝试检查是否 type === 'Application'
,并返回 null(虽然我明白为什么这不起作用),返回 Application
(GraphQLObject),但这不起作用......不真的很确定从那里去哪里。
- 您需要为 GraphQL 自动生成唯一的全局 ID
您要重新获取的类型。
- 在
nodeInterface
你告诉 GraphQL
如何将id映射到对应的GraphQL对象。
- 通过给定的服务器端对象
nodeInterface
识别GraphQL类型。
下面是应用程序的简化示例:
// nodeInterface.
var {nodeInterface, nodeField} = nodeDefinitions(
(globalId) => {
var {type, id} = fromGlobalId(globalId);
// The mapping from globalId to actual object id and type.
console.log('globalId:', id);
console.log('type:', type);
if (type === 'Application') {
// getApplication is your db method to retrieve Application object.
// With id you could also retrieve a specific db object.
return getApplication();
} else {
return null;
}
},
(obj) => {
// Note that instanceof does an identity check on the prototype object, so it can be easily fooled.
if (obj instanceof Application) {
return ApplicationType;
} else {
return null;
}
},
);
// Application.
export const ApplicationType = new GraphQLObjectType({
name: 'Application',
fields: () => ({
// Auto-generated, globally defined id.
id: globalIdField('Application'),
_id: {
type: GraphQLString,
resolve: () => 'APPLICATION_ID'
},
invites: {
type: InviteConnectionType,
args: connectionArgs,
resolve: (application, args) => {
...
}
}
}),
// Declaring nodeInterface.
interfaces: [nodeInterface]
});
请注意,在初始提取期间 nodeInterface
甚至不会执行,因此如果 nodeInterface
没有返回任何内容,则在初始提取时不会出现错误。如果这没有意义或者您仍在努力,您可以 post 一个 link 到回购协议,我会调查它。
要对此进行更新,我走在正确的道路上。
目前的 nodeDefinitions
我只是需要一点额外的:
nodeDefinitions(
(globalId) => {
const { type, id } = fromGlobalId(globalId)
if (type === 'Application') {
return Promise.resolve(Application)
}
return db[type].findById(id)
},
(obj) => {
if (obj.$modelOptions) {
/* sequelize object */
const name = obj.$modelOptions.name.singular
return types[name]
} else if (obj.name === 'Application') {
return Application
}
return null
}
)
我不确定这是否是最好的方法,但它似乎可以解决问题。要点是,如果我想要 returned 的节点类型是 Application
,我 return GraphQL 对象 - { ... name: "Application" ... }
我们将使用 name
字段从下一步(nodeDefinitions
中的第二个回调)到只是重新 return Application
。我认为您可以 return 一个 "custom" 对象或其他对象 - 只要您 return 可以定义从 GraphQLObject
的映射的独特对象就没关系类型(第二次回调需要)。
在这种情况下,类型 "X" 是 Application
,类型 "Y" 是类型 "Node" - 我明白了 为什么会这样,但我对 Relay 的理解不足以理解如何修复它。中继生成的查询是
query {
node(id: $some_id) {
...F0
}
}
fragment F0 on Application {
...
}
我的架构看起来像
query {
application {
/* kind of a generic endpoint for fetching lists, etc */
invites(token: $token) {
name
}
}
viewer { /* the current user */ }
}
我正在尝试从会话外部获取特定邀请(viewer
是 null
)。
我试过了
const application = Relay.QL`query { application }`
...
<Route ... queries={{ application }}/>
...
Relay.createContainer(Component, {
initialValues: { token: null },
fragments: {
application: () => {
fragment on Application {
invites(token: $token) {
...
}
}
}
}
})
这给了我错误
片段 "F0" 不能在这里传播,因为类型 "Node" 的对象永远不能是类型 "Application" - 或者类似的东西。
我有点困惑,因为如果我要编写原始查询并 运行 直接通过 GraphQL
query {
application {
invites(token: "asdasdasd") {
edges {
node {
name
}
}
}
}
}
它给了我想要的东西...
在后端,我的图表定义如下
export const Application = new GraphQLObjectType({
name: 'Application',
fields: () => ({
id: {
type: GraphQLString,
resolve: () => 'APPLICATION_ID'
},
invites: {
type: InviteConnectionType,
args: connectionArgs,
resolve: (application, args) => {
...
}
}
})
})
export default new GraphQLSchema({
query: new GraphQLObjectType({
name: 'query',
fields: {
node: nodeField,
application: {
type: Application,
resolve: (root, args, ctx) => {
return Promise.resolve({})
}
}
}
})
我一直在看 this and some issues on the Relay github 这样的问题,但我不清楚我应该如何实施 nodeInterface
。
编辑:当前nodeInterface
代码的短-长是
export const {
nodeInterface,
nodeField
} = nodeDefinitions(
(globalId) => {
const { type, id } = fromGlobalId(globalId)
return db[type].findById(id)
},
(obj) => {
const name = obj.$modelOptions.name.singular
return types[name]
}
)
应用程序不是数据库模型,但是,它只是一个用于获取数据的通用接口。我已经尝试检查是否 type === 'Application'
,并返回 null(虽然我明白为什么这不起作用),返回 Application
(GraphQLObject),但这不起作用......不真的很确定从那里去哪里。
- 您需要为 GraphQL 自动生成唯一的全局 ID 您要重新获取的类型。
- 在
nodeInterface
你告诉 GraphQL 如何将id映射到对应的GraphQL对象。 - 通过给定的服务器端对象
nodeInterface
识别GraphQL类型。
下面是应用程序的简化示例:
// nodeInterface.
var {nodeInterface, nodeField} = nodeDefinitions(
(globalId) => {
var {type, id} = fromGlobalId(globalId);
// The mapping from globalId to actual object id and type.
console.log('globalId:', id);
console.log('type:', type);
if (type === 'Application') {
// getApplication is your db method to retrieve Application object.
// With id you could also retrieve a specific db object.
return getApplication();
} else {
return null;
}
},
(obj) => {
// Note that instanceof does an identity check on the prototype object, so it can be easily fooled.
if (obj instanceof Application) {
return ApplicationType;
} else {
return null;
}
},
);
// Application.
export const ApplicationType = new GraphQLObjectType({
name: 'Application',
fields: () => ({
// Auto-generated, globally defined id.
id: globalIdField('Application'),
_id: {
type: GraphQLString,
resolve: () => 'APPLICATION_ID'
},
invites: {
type: InviteConnectionType,
args: connectionArgs,
resolve: (application, args) => {
...
}
}
}),
// Declaring nodeInterface.
interfaces: [nodeInterface]
});
请注意,在初始提取期间 nodeInterface
甚至不会执行,因此如果 nodeInterface
没有返回任何内容,则在初始提取时不会出现错误。如果这没有意义或者您仍在努力,您可以 post 一个 link 到回购协议,我会调查它。
要对此进行更新,我走在正确的道路上。
目前的 nodeDefinitions
我只是需要一点额外的:
nodeDefinitions(
(globalId) => {
const { type, id } = fromGlobalId(globalId)
if (type === 'Application') {
return Promise.resolve(Application)
}
return db[type].findById(id)
},
(obj) => {
if (obj.$modelOptions) {
/* sequelize object */
const name = obj.$modelOptions.name.singular
return types[name]
} else if (obj.name === 'Application') {
return Application
}
return null
}
)
我不确定这是否是最好的方法,但它似乎可以解决问题。要点是,如果我想要 returned 的节点类型是 Application
,我 return GraphQL 对象 - { ... name: "Application" ... }
我们将使用 name
字段从下一步(nodeDefinitions
中的第二个回调)到只是重新 return Application
。我认为您可以 return 一个 "custom" 对象或其他对象 - 只要您 return 可以定义从 GraphQLObject
的映射的独特对象就没关系类型(第二次回调需要)。