I can successfully do graphql/relay queries and mutations with CURL and GraphiQL tool:
However, in my react/relay app I can query and get the data into the app, but every time I try to mutate something in my app, I get this error in the console:
bundle.js:51511 Uncaught Error: GraphQL validation error ``Cannot query field "store" on type "CreateLinkPayload".`` in file
`/Users/johndoe/react-relay-project/src/mutations/CreateLinkMutation.js`. Try updating your GraphQL schema if an argument/field/type was recently added.
(anonymous function) @ bundle.js:51511
getFatQuery @ bundle.js:51512
getFatQuery @ bundle.js:35664
getQuery @ bundle.js:35791
_handleCommit @ bundle.js:35539
commit @ bundle.js:35453
commit @ bundle.js:35894
(anonymous function) @ bundle.js:28526
and every time I do npm start
I get this error:
-- GraphQL Validation Error -- CreateLinkMutation --
File: /Users/johndoe/react-relay-project/src/mutations/CreateLinkMutation.js
Error: Cannot query field "store" on type "CreateLinkPayload".
Source:
>
> store { linkConnection }
> ^^^
CreateLinkMutation.js
import Relay from 'react-relay'
class CreateLinkMutation extends Relay.Mutation {
getMutation() {
return Relay.QL`
mutation { createLink }
`
}
getVariables() {
return {
title: this.props.title,
url: this.props.url
}
}
getFatQuery() {
return Relay.QL`
fragment on CreateLinkPayload {
linkEdge,
store { linkConnection }
}
`
}
getConfigs() {
return [{
type: 'RANGE_ADD',
parentName: 'store',
parentID: this.props.store.id,
connectionName: 'linkConnection',
edgeName: 'linkEdge',
rangeBehaviors: {
'': 'append'
}
}]
}
}
export default CreateLinkMutation
parts of Link.js
Link = Relay.createContainer(Link, {
fragments: {
link: () => Relay.QL`
fragment on Link {
url,
title
}
`
}
})
parts of App.js
handleSubmit(e) {
e.preventDefault()
Relay.Store.update(
new CreateLinkMutation({
title: this.refs.newTitle.value,
url: this.refs.newUrl.value,
store: this.props.store
})
)
this.refs.newTitle.value = ''
this.refs.newUrl.value = ''
}
App = Relay.createContainer(App, {
initialVariables: {
limit: 10
},
fragments: {
store: () => Relay.QL`
fragment on Store {
id,
linkConnection(first: $limit) {
edges {
node {
id,
${Link.getFragment('link')}
}
}
}
}
`
}
})
parts of main.js
class LinkStoreRoute extends Relay.Route {
static routeName = 'LinkStoreRoute'
static queries = {
store: () => Relay.QL`query { store }`
}
}
My schema.js
:
const store = {}
const Store = new GraphQLObjectType({
name: 'Store',
fields: () => ({
id: globalIdField('Store'),
linkConnection: {
type: linkConnection.connectionType,
args: connectionArgs,
resolve: (_, args) => {
return docClient.scan(
Object.assign(
{},
{TableName: linksTable},
paginationToParams(args)
)
).promise().then(dataToConnection)
}
}
})
})
const Link = new GraphQLObjectType({
name: 'Link',
fields: () => ({
id: {
type: new GraphQLNonNull(GraphQLID),
resolve: (obj) => obj.id
},
title: { type: GraphQLString },
url: { type: GraphQLString }
})
})
const linkConnection = connectionDefinitions({
name: 'Link',
nodeType: Link
})
let createLinkMutation = mutationWithClientMutationId({
name: 'CreateLink',
inputFields: {
title: { type: new GraphQLNonNull(GraphQLString) },
url: { type: new GraphQLNonNull(GraphQLString) }
},
outputFields: {
linkEdge: {
type: linkConnection.edgeType,
resolve: (obj) => ({node: obj, cursor: obj.id})
}
},
store: {
type: Store,
resolve: () => store
},
mutateAndGetPayload: (inputFields) => {
let link = {
id: uuid.v4(),
title: inputFields.title,
url: inputFields.url
}
return new Promise((resolve, reject) => {
docClient.put(
Object.assign(
{},
{TableName: linksTable},
{Item: link}
),
(err, data) => {
if (err) return reject(err)
return resolve(link)
}
)
})
}
})
const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: () => ({
store: {
type: Store,
resolve: () => store
}
})
}),
mutation: new GraphQLObjectType({
name: 'Mutation',
fields: () => ({
createLink: createLinkMutation
})
})
})
module.exports = schema
Note that I excluded 40 lines of require
statements at the top.
How is this even possible? And how can I fix it? Could it be a bug of relay/react?
In your client-side implementation of CreateLinkMutation
(CreateLinkMutation.js file), getFatQuery()
function specifies that it expects two outputs after the mutation is complete - linkEdge
and store
. Therefore, in your server-side implementation of the mutation, you must include these two things as output. However, only linkEdge
is included to the mutation's outputs in your current implementation (createLinkMutation
in schema.js file). To solve the problem, include store
to the outputs.
outputFields: {
linkEdge: {
type: linkConnection.edgeType,
resolve: (obj) => ({node: obj, cursor: obj.id})
},
store: {
type: Store,
resolve: () => store
},
},
Turns out store
store: {
type: Store,
resolve: () => store
}
has to go inside outputFields like so:
outputFields: {
linkEdge: {
type: linkConnection.edgeType,
resolve: (obj) => ({node: obj, cursor: obj.id})
}
store: {
type: Store,
resolve: () => store
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With