I'm writing a relay.js app, and I'm using react-relay-router for routing. Routing works, but I believe it is exposing a misunderstanding on my part of how to organize query fragments across different views.
routes defined in app.js
const rootComponent =
(<RelayRouter history={hashHistory}>
<Route path="/"
component={App}
queries={ViewerQueries}
onReadyStateChange={this.handleStateChange}
>
<IndexRoute
component={Dashboard}
queries={ViewerQueries}
/>
<Route
path="/org_setup"
component={OrgSetup}
queries={ViewerQueries}
/>
<Route
path="/admin/data_models"
component={DataModelList}
queries={ViewerQueries}
/>
</Route>
</RelayRouter>);
ReactDOM.render(rootComponent, mountNode);
query fragment declaration in DataModelList.js
export default Relay.createContainer(DataModelList, {
fragments: {
viewer: () => Relay.QL`
fragment on User {
dataModels(first: 10) {
edges {
node {
id,
name,
isAuthority,
categories(first: 10) {
edges {
node {
id,
name,
tags(first: 10) {
edges {
node {
id,
code,
label,
}
}
}
}
}
},
adapter {
categories(first: 10) {
edges {
node {
id,
name,
}
}
}
}
}
}
},
}
`,
},
});
query fragment in OrgSetup.js
export default Relay.createContainer(OrgSetup, {
fragments: {
viewer: () => Relay.QL`
fragment on User {
dataModels(first: 10) {
edges {
node {
id,
name,
isAuthority,
categories(first: 10) {
edges {
node {
id,
name,
tags(first: 10) {
edges {
node {
id,
code,
label,
}
}
}
}
}
},
}
}
},
}
`,
},
});
When navigating between DataModelList
and OrgSetup
(in either direction) I see the following error in the console:
Server request for query `ViewerQueries` failed for the following reasons:
1. Cannot query field "node" on "Query".
rQueries($id_0:ID!){node(id:$id_0){id,__typename,...F0}} fra
Warning: RelayReadyState: Invalid state change from
{"aborted":false,"done":false,"error":{"source":{"data":null,"errors":
[{"message":"Cannot query field \"node\" on \"Query\".","locations":
[{"line":1,"column":32}]}]}},"ready":false,"stale":false}` to `{"error":
{"source":{"data":null,"errors":[{"message":"Cannot query field \"node\" on
\"Query\".","locations":[{"line":1,"column":32}]}]}}}`.warning @
app.js:31567update @ app.js:39409onRejected @ app.js:39035tryCallOne @
app.js:30045(anonymous function) @ app.js:30131flush @ app.js:30279
I'm able to prevent this error from occurring by making the query fragments in the two views identical - specifically by adding the adapter
fragment.
However, this feels wrong. They don't need to be identical (in fact they are somewhat intentionally bloated at the moment since this is a learning app for me), and other views will of course not share these data needs.
viewer
and their dataModels
, and then allow child
components to express their needs, requesting any nested data (eg
categories
, tags
, or adapters
and their respective categories
).invalid state change
error really mean? I can see
that it's satisfied by the queries matching exactly, but I can't
imagine unrelated views are required to share query declarations. I
suspect this is a byproduct of my doing something wrong elsewhere.Thanks!
When the query changes (eg. due to a route transition, or a call to setVariables()
) Relay will diff the query you're coming from and the query you're headed to, computing the minimal query to get you from A to B. In your case, Relay starts from the series of known records stored on the client (the already-fetched ones) and tries to fetch only the new fields on those exact records in an effort to build a complete picture of the world. These refetches rely on something called the node interface.
Relay-compliant GraphQL servers must expose a root field called node
that can fetch any record given a global ID. This field must take an id
argument of type GraphQLID!
.
For an example of how to build such a root field, see this graphql-js
example.