使用具有不同片段字段的相同中继根查询的多个 react-router-relay 路由
Posted
技术标签:
【中文标题】使用具有不同片段字段的相同中继根查询的多个 react-router-relay 路由【英文标题】:Multiple react-router-relay routes using same Relay root query with different fragment fields 【发布时间】:2016-01-09 15:45:39 【问题描述】:我遇到了一个问题,当使用相同的根查询在两个相邻的 react-router-relay 路由组件中请求数据时,第二个路由组件中的 graphql 服务器查询会使之前从第一个检索到的数据无效。
举个例子:
我正在使用一种解决方法将字段附加到“查看器”根节点,以便从根字段查询数据数组:
我的 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 组件仅包含 'name' 字段,则 Relay 不会正确地发出另一个服务器请求,而是用数据填充数组(假设从初始 App 组件服务器请求中缓存)。
难道不应该可以从任一组件获取汽车数组,而无论它们在路线中出现的顺序如何,Relay 都可以获取片段中指定的任何其他数据字段吗?
任何帮助将不胜感激!
【问题讨论】:
【参考方案1】:(发布为答案,因为我无法在评论中格式化代码。)
您描述的场景听起来非常适合使用嵌套路由:
ReactDOM.render(
<Router createElement=ReactRouterRelay.createElement>
<Route path="/" component=App queries=ViewerQueries>
<Route path="/cars" component=AllCars queries=ViewerQueries />
</Route>
</Router>,
document.getElementById('ReactContainer')
);
如果您仍然看到具有该结构的空数组,您能否提供指向包含通过网络发送的查询和响应的要点的链接?
【讨论】:
谢谢,这可能是处理对同一源数据类型的查询的首选方法。但是,我暂时将其保持打开状态,我将尝试找到一种方法来处理原始场景而无需嵌套,因为能够查询相同的数据源类型(并包含不同的数据元素)可能很有用在非嵌套的对于schema.js
文件中的(示例)Car
类型,问题最终无效nodedefinitions
。
我最终使用的节点定义是:
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 请求的额外数据点,导致返回 null 值,从而有效地取消了之前获取的 Car
项目。
另外,根定义无效,应该是:
var Root = new GraphQLObjectType(
name: 'Root',
fields:
viewer:
type: GraphQLUser,
resolve: (root, ) => getUser()
,
node: nodeDefinitions.nodeField
);
node
字段定义错误导致 GraphQL 服务器抱怨无法查询根查询中的“节点”字段。
在这些更正之后,Relay 能够使用不同的数据点查询相同的 Root 字段,而不管在 <Route/>
树中的位置。
虽然嵌套路由可能更适合于相同对象类型的主/详细列表,但有时希望在不相关的 React 组件中包含相同的数据(例如侧边栏、标题等)
【讨论】:
以上是关于使用具有不同片段字段的相同中继根查询的多个 react-router-relay 路由的主要内容,如果未能解决你的问题,请参考以下文章