我遇到的问题是,当使用相同的根查询在两个相邻的react-router-relay路由组件中请求数据时,第二个路由组件中的graphql server查询会使之前从第一个路由组件中检索的数据无效。
举个例子:
我正在使用一种解决方法将字段附加到“查看器”根节点,以便从根字段查询数据数组:
我的schema.js包含以下查看器(用户)类型和根目录的定义:
var GraphQLUser = new GraphQLObjectType({
name: 'User',
isTypeOf: function(obj) { return obj instanceof User },
fields: function() {
return {
id: GraphQLRelay.globalIdField('User'),
//Fields to expose to app, e.g. cars
cars: {
type: GraphQLRelay.connectionDefinitions({
name: 'Car', nodeType: carType
}).connectionType,
args: GraphQLRelay.connectionArgs,
resolve: function(user, args) {
return
GraphQLRelay.connectionFromPromisedArray(getCars(), args)
},
},
}
},
interfaces: [nodeDefinitions.nodeInterface],
});
根源:
var Root = new GraphQLObjectType({
name: 'Root',
fields: {
viewer: {
type: GraphQLUser,
resolve: (root, {} ) => getUser()
},
node: nodeDefinitions.nodeField
});
现在,在main.jsx应用程序入口点,我定义了以下路由:
ReactDOM.render(
<Router createElement={ReactRouterRelay.createElement}>
<Route path="/" component={App} queries={ViewerQueries} />
<Route path="/cars" component={AllCars} queries={ViewerQueries} />
</Router>,
document.getElementById('ReactContainer'));
包含ViewerQueries.js:
export default {
viewer: () => Relay.QL`query { viewer }`,
};
现在,如果App
组件包含以下graphql片段:
exports.Component = Relay.createContainer(App, {
initialVariables: {
limit: 10
},
fragments: {
viewer: () => Relay.QL`
fragment on User {
cars (first: $limit) {
edges {
node {
name,
}
}
}
}`,
},
})
AllCars
组件包含以下内容:
exports.Component = Relay.createContainer(AllCars, {
initialVariables: {limit: 10},
fragments: {
viewer: () => Relay.QL`
fragment on User {
cars (first: $limit) {
edges {
node {
name,
type
}
}
}
}`,
},
})
在路径'/'上呈现App组件时会发生什么,返回的汽车数组没有问题。但是,一旦'/ cars'路径被渲染,`this.props.viewer.cars'上的结果数组为空。此外,返回路径'/'以重新呈现App组件现在也返回一个空数组。
在后端,似乎AllCars组件导致服务器额外POST /graphql 200 277.369 ms - 94
行,以获取片段中指定的新type
。
如果AllCars组件仅包含“名称”字段,则Relay正确地不会发出另一个服务器请求,而是使用数据填充数组(假设从初始App组件服务器请求缓存)。
不可能从任一组件获取汽车数组,Relay会获得碎片中指定的任何其他数据字段,而不管它们在路径中出现的顺序如何?
非常感谢任何帮助!
答案 0 :(得分:2)
(发布回答是因为我无法在评论中格式化代码。)
您描述的场景听起来非常适合使用嵌套路线:
ReactDOM.render(
<Router createElement={ReactRouterRelay.createElement}>
<Route path="/" component={App} queries={ViewerQueries}>
<Route path="/cars" component={AllCars} queries={ViewerQueries} />
</Route>
</Router>,
document.getElementById('ReactContainer')
);
如果您仍然看到具有该结构的空数组,您是否可以提供指向包含通过网络发送的查询和响应的要点的链接?
答案 1 :(得分:0)
问题最终导致nodedefinitions
文件中的{example} Car
类型无效schema.js
。
我最终使用的节点定义是:
var nodeDefinitions = GraphQLRelay.nodeDefinitions(function(globalId) {
var idInfo = GraphQLRelay.fromGlobalId(globalId)
if (idInfo.type == 'Car') {
return getCarById(idInfo.id)
} else if ...
// Other types here
}
return null
});
返回的getCarById函数没有正确解析Car对象,并且GraphQL服务器无法获取Relay请求的其他数据点,导致返回空值,从而有效地使先前获取的{无效{ {1}}项目。
此外,Root定义无效,应该是:
Car
错误放置的var Root = new GraphQLObjectType({
name: 'Root',
fields: {
viewer: {
type: GraphQLUser,
resolve: (root, {} ) => getUser()
},
node: nodeDefinitions.nodeField
}
});
字段定义导致GraphQL服务器抱怨无法查询&#39;节点&#39; Root查询字段。
经过这些更正后,无论node
树中的位置如何,Relay都可以使用不同的数据点查询相同的根字段。
虽然嵌套路由可能是同一对象类型的主/详细列表的首选,但有时需要在不相关的React组件中包含相同的数据(例如侧边栏,标题等)