I was trying to list users in my app and I encountered with a strange behaviour when I was trying to implement the filtering feature to my users
query.
I'm using React-Router and below in the code, I'm getting URL query and pass it to users
query. It works as expected at first with any query. But when I run -let's say- browserHistory.push('users?username=test')
to push a new state and change the query, apollo client sends the query again but also UsersFilterInput
(which I believe it should not send)
Here's my wrapper;
const QUERY = gql`
query Users($query: UsersFilterInput) {
users(query: $query) {
id
username
nickname
level
avatar
createdAt
}
}
input UsersFilterInput {
page: Int
orderBy: String
orderDir: String
username: String
nickname: String
level: String
}
`;
@graphql(QUERY, {
options({ location: { query } }) {
return {
variables: {
query,
},
};
},
})
Here's the working first query that sent to server;
{"query":"query Users($query: UsersFilterInput) {\n users(query: $query) {\n id\n username\n nickname\n level\n avatar\n createdAt\n }\n}\n","variables":{"query":{"page":"0"}},"operationName":"Users"}
Here's the broken second query that sent to server;
{"query":"query Users($query: UsersFilterInput) {\n users(query: $query) {\n id\n username\n nickname\n level\n avatar\n createdAt\n }\n}\n\ninput UsersFilterInput {\n page: Int\n orderBy: String\n orderDir: String\n username: String\n nickname: String\n level: String\n}\n","variables":{"query":{"username":"ad"}},"operationName":"Users"}
And the error message from server
{"errors":[{"message":"GraphQL cannot execute a request containing a InputObjectTypeDefinition.","locations":[{"line":12,"column":1}]}]}
I don't think your query is valid GraphQL syntax. The input type definition needs to go into the server's schema, you can't add input types on the client.
We didn't foresee the situation, so there isn't a good error message for this.
What was your intention when including the input type definition in the query?
I already defined the same input definition at server side. I am new to graphql so I thought I needed to send an input object with the same structure from client. That's why I tried to create a definition at client and attach it to query.
Edit: Also since the first query that sent is working as expected, I thought that was actually valid.
Yeah, I think we should have a better error there. You only need to define the input type on the server.
Just to be clear, do i have to pass each variable individually to that query? Like;
query Users($page: Int, $username: String){
users(query: { page: $page, username: $username }) {
Or is there any other solution you can point me?
No, you can just use the input type:
const QUERY = gql`
query Users($query: UsersFilterInput) {
users(query: $query) {
id
username
nickname
level
avatar
createdAt
}
}
`;
Since the server already knows about the input type, you don't need to do anything extra.
That's great. It's working like a charm now, thank you.
Yeah an easy way to test this stuff out is to put it in GraphiQL instead. If it works in GraphiQL, it will work in Apollo Client.
Want to submit a PR to add a better message? It should be easy to just add an if statement here: https://github.com/apollostack/apollo-client/blob/e14c50dc8362c72d4bda51684f2269d86c71bb00/src/queries/getFromAST.ts#L42
I think you could check for anything that's not an OperationDefinition
or FragmentDefinition
, and say something like "Schema type definitions not allowed in queries."
Sorry to open this again, but is there a way to do this without reusing server schema? Working on the case with separate client and API.
The following illustrates what I'm trying to do, but getting syntax error.
const updateProfile = gql`
type Profile {
firstName: String!
lastName: String!
position: String!
}
mutation updateProfile($_id: String!, $profile: Profile) {
updateProfile(_id: $_id, profile: $profile) {
_id
}
}
`;
this works for me thanks
Sorry to open this again, but is there a way to do this without reusing server schema? Working on the case with separate client and API.
The following illustrates what I'm trying to do, but getting syntax error.
const updateProfile = gql` type Profile { firstName: String! lastName: String! position: String! } mutation updateProfile($_id: String!, $profile: Profile) { updateProfile(_id: $_id, profile: $profile) { _id } } `;
Any solutions for this? Also running into same trouble.
@PendicGordan - you can define a client schema, check the docs
Most helpful comment
No, you can just use the input type:
Since the server already knows about the input type, you don't need to do anything extra.