中继重新获取失败...错误中继无法协调连接上的边缘
Posted
技术标签:
【中文标题】中继重新获取失败...错误中继无法协调连接上的边缘【英文标题】:Relay re-fetching failed... error Relay was unable to reconcile edges on a connection 【发布时间】:2016-11-24 12:08:51 【问题描述】:请帮忙!也许有人已经遇到了我的问题....
当使用更新的变量重新获取数据时 -- 使用 relay.setVariables() -- 我收到错误 "Relay 无法协调连接上的边缘。这很可能在尝试处理服务器响应时发生,该响应包括与缺少id
字段的节点的连接边缘。” 尽管数据正确,但中继存储并未更新。
见下面的代码...(Ruby && ES6)
宝石文件
gem 'graphql', '0.16.0'
gem 'graphql-relay', '0.11.2'
....服务器端代码
node_identification.rb
NodeIdentification = GraphQL::Relay::GlobalNodeIdentification.define do
object_from_id -> (id, ctx) do
type, id = NodeIdentification.from_global_id(id)
case type
when 'FrontApp'
Relay::FrontApp::STATIC
else
Object.const_get(type).find_by(id: id)
end
end
type_from_object -> (obj) do
begin
MODEL_TO_TYPE[obj.class.name.to_sym].constantize
rescue
(obj.class.name + 'Type').constantize
end
end
end
MODEL_TO_TYPE =
:'Relay::FrontApp' => 'FrontAppType'
front_app_query_type.rb
FrontAppQueryType = GraphQL::ObjectType.define do
name 'FrontAppRootQuery'
field :node, field: NodeIdentification.field
field :main, FrontAppType do
resolve -> (obj, args, ctx)
Relay::FrontApp::STATIC
end
end
front_app_type.rb
FrontAppType = GraphQL::ObjectType.define do
name 'FrontApp'
# field :node, field: NodeIdentification.field
interfaces [NodeIdentification.interface]
global_id_field :id
field :tips, TipsType do
argument :filters, types.String
resolve -> (obj, args, ctx)
filters = args[:filters]
begin
filters = JSON.parse(filters).deep_symbolize_keys!
rescue
filters = nil
end
ctx[:filters] = filters
Relay::Tips::STATIC
end
connection :footer, FooterMenuItemType.connection_type do
argument :id, types.ID!
resolve ->(obj, args, ctx)
::Footer.order(:id)
end
end
tips_connection_type.rb
TipsConnectionType = TipShowType.define_connection do
field :totalCount, types.Int do
resolve -> (obj, args, ctx)
obj.object.size
end
end
TipsType = GraphQL::ObjectType.define do
name 'Tips'
description 'Tips list for home page'
interfaces [NodeIdentification.interface]
global_id_field :id
connection :mostRecent, TipsConnectionType do
argument :limit, types.Int
resolve ->(obj, args, ctx)
tips = ::Tip.active_users.started(Time.zone.now.in_time_zone(ctx[:current_user] ? ctx[:current_user].time_zone : ::User.get_locally_time_zone).to_date).ready.active.moderated.published.includes(:comments, :tip_type).order('created_at desc').limit(args[:limit])
TipHelpers::Filter.filter(tips: tips, filters: ctx[:filters], reorder: 'created_at desc')
end
connection :mostPopular, TipsConnectionType do
argument :limit, types.Int
resolve ->(obj, args, ctx)
tips = ::Tip.active_users.started(Time.zone.now.in_time_zone(ctx[:current_user] ? ctx[:current_user].time_zone : ::User.get_locally_time_zone).to_date).ready.active.moderated.published.includes(:comments, :tip_type).order('(SELECT COUNT(*) FROM comments WHERE tid = tips.id) desc').limit(args[:limit])
TipHelpers::Filter.filter(tips: tips, filters: ctx[:filters], reorder: '(SELECT COUNT(*) FROM comments WHERE tid = tips.id) desc')
end
end
/app/models/relay/front_app.rb
module Relay
class FrontApp < Struct.new :id
# HACK::// For relay root queries
STATIC = new(id: 'main').freeze
def initialize *args
opts = args.last.is_a?(Hash) ? args.pop : Hash.new
super *args
opts.each_pair do |k, v|
self.send "#k=", v
end
end
def self.find(_)
STATIC
end
end
end
** /app/models/relay/tips.rb**
module Relay
class Tips < Struct.new :id
# HACK:// For relay root queries
STATIC = new(id: 'tips').freeze
def initialize *args
opts = args.last.is_a?(Hash) ? args.pop : Hash.new
super *args
opts.each_pair do |k, v|
self.send "#k=", v
end
end
def self.find(_)
STATIC
end
end
end
....和客户端代码
class MainApp extends React.Component
constructor(props)
super(props);
this.state =
filters: filtersTemplate
;
this.setFilter = this.setFilter.bind(this);
setFilter(filter, value, e)
if (e)
e.nativeEvent.stopImmediatePropagation();
e.preventDefault();
let filters = this.state;
if (['currency', 'sum'].inArray(filter))
filters.funds[filter] = value;
else
filters[filter] = value;
this.setState(
filters: filters
);
this.props.relay.setVariables(filters: filters);
render()
let tips = this.props.main;
let renderTipsSection = (section) =>
let tipsCount = tips[section] ? tips[section].edges.length : 0;
let blankCount = 10 - tipsCount;
return (
<ul className="tips__list">
tips[section] && tips[section].edges.map((node) => (
<li key=node.id className="tips__list_item">
<TipCard node=node/>
</li>
))
[...new Array(blankCount).keys()].map((item, idx) => (
<li key=idx className="tips__list_item">
<TipCard dummy=true/>
</li>
))
</ul>
);
;
return (
<div>
<div className="wrapper">
<div className="TipsWrapper">
<div className="wrapper">
renderTipsSection('mostRecent')
renderTipsSection('mostPopular')
</div>
</div>
</div>
</div>
);
export default Relay.createContainer(MainApp,
initialVariables:
filters:
category: null,
funds:
currency: null,
sum: null
,
date: null,
location: null,
browse: null
,
prepareVariables: (prevVars) =>
return
...prevVars,
filters: JSON.stringify(prevVars.filters)
,
fragments:
main: () => Relay.QL`
fragment on FrontApp
tips(filters: $filters)
mostRecent(first: 10, limit: 10)
edges
node
id
tid
title_name
category
mostPopular(first: 10, limit: 10)
edges
node
id
tid
title_name
category
`
);
当 setFilter() 触发时,将调用 relay.setVariables... 结果……
[RELAY-NETWORK] Run query q3 Object relayReqId: "q3", relayReqObj: RelayQueryRequest, relayReqType: "query", method: "POST", headers: Object…
[RELAY-NETWORK] query q3: 3429ms
Warning: Relay was unable to reconcile edges on a connection. This most likely occurred while trying to handle a server response that includes connection edges with nodes that lack an `id` field
【问题讨论】:
能否也包含TipShowType
的代码? (那是有问题的连接的edge
,对吧?)
发送到https://github.com/rmosolgo/graphql-relay-ruby/issues/61
我通过 FIELDS_CHANGE 行为解决了这个问题
上面可以看到的解决方案
你应该把你的问题和答案分开。
【参考方案1】:
经过数小时的折腾,找到了上述问题的解决方案……见下文
解决方案
客户端突变
export default class ApplyFiltersMutation extends Relay.Mutation
static fragments =
tips: () => Relay.QL`
fragment on Tips
id
`,
;
getMutation()
return Relay.QL`mutation
applyFilters
`;
getVariables()
return
filters: this.props.filters
;
getFatQuery()
return Relay.QL`
fragment on ApplyFiltersPayload
tips
`;
getConfigs()
return [
type: 'FIELDS_CHANGE',
fieldIDs: tips: this.props.tips.id,
];
服务器端
home_mutations.rb
module HomeMutations
ApplyFilters = GraphQL::Relay::Mutation.define do
name 'ApplyFilters'
input_field :filters, !types.String
return_field :tips, BipsType
resolve -> (args, ctx)
filters = args[:filters]
begin
filters = JSON.parse(filters).deep_symbolize_keys!
rescue
filters = nil
end
ctx[:filters] = filters
tips: Relay::Tips::STATIC
end
end
tips_type.rb
include TipHelpers::Filter
TipsType = GraphQL::ObjectType.define do
name 'Tips'
description 'Tips list for home page'
interfaces [NodeIdentification.interface]
global_id_field :id
connection :almostRaised, TipsConnectionType do
resolve ->(obj, args, ctx)
TipHelpers::Filter.filter(section: 'almost_raised', filters: ctx[:filters], current_user: ctx[:current_user])
end
...
end
end
lib/tip_helpers.rb
class TipHelpers
module Filter
def filter(section:, filters:, current_user:)
...
# p tips.reorder(reorder).to_sql
tips.reorder(reorder)
end
end
end
【讨论】:
答案能否具体说明解决方案的具体应用位置?以上是关于中继重新获取失败...错误中继无法协调连接上的边缘的主要内容,如果未能解决你的问题,请参考以下文章
尝试从反应应用程序连接到 graphcool 中继 API 时出现此错误:模块构建失败:错误:没有有效的 GraphQL 端点