在这种情况下,键入“X”为Application
,类型“Y”为“Node”类型 - 我可以看到为什么会发生这种情况,但我对Relay的理解不是'足以理解如何解决它。 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”不能在这里传播,因为“节点”类型的对象永远不能是“应用程序”类型 - 或者是那种效果。
我有点困惑,因为如果我要写一个原始查询并直接通过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和一些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),但这不起作用...不真的很确定从哪里去。
答案 0 :(得分:1)
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
没有返回任何内容,则初始提取时不会出现错误。如果这没有意义,或者你仍在努力,你可以发布一个链接到回购,我会调查它。
答案 1 :(得分:1)
为了对此进行更新,我走的是正确的道路。
当前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
}
)
我不确定这是否是最好的方法,但它似乎可以解决问题。要点是,如果我想要返回的节点类型是Application
,我将返回GraphQL对象 - { ... name: "Application" ... }
我们将在下一个中使用name
字段step(nodeDefinitions
中的第二个回调)只是重新返回Application
。我认为你可以返回一个“自定义”对象或其他东西 - 只要你返回一些独特的东西就可以了,你可以定义一个映射到GraphQLObject
类型(第二个回调需要)。< / p>