I'm just putting this here for future reference. I took a few months off from GraphQL. When I came back I coded a new resolver and it was returning with loading
=== false but data
=== 'undefined'. The solution revealed a tweaky detail about setting up GraphQL types and queries, that probably any number of people just learning GraphQL struggle with.
In seeking the answer, I searched many SO posts and other articles dealing with loading
=== false but data
=== 'undefined', but didn't see one that described the info I needed to solve it in my case.
Here's the setup that did not work:
SCHEMA
type BraintreeClientToken{
clientToken: String
}
type query{
getBraintreeClientToken(localUserId: String!): BraintreeClientToken
}
QUERY LIBRARY
This is the code that had the error
const GETBRAINTREECLIENTTOKEN_QUERY = gql`
query ($localUserId: String!) {
getBraintreeClientToken(localUserId: $localUserId) {
BraintreeClientToken
}
}
`;
RESOLVERS
getBraintreeClientToken: (parent, args, context) => {
const userid = context.userId;
let BraintreeClientToken = {
clientToken: '',
}
return Promise.resolve()
.then(() => {
//CODE HERE THAT CORRECTLY OBTAINS THE CLIENTTOKEN FROM THE BRAINTREE API -- NOT RELEVANT TO THIS POST
return clientToken;
})
.then((clientToken) => {
BraintreeClientToken.__typename = 'BraintreeClientToken';
BraintreeClientToken.clientToken = clientToken.clientToken;
return BraintreeClientToken;
})
.then((BraintreeClientToken) => {
return BraintreeClientToken;
})
.catch((err) => {
console.log(err);
});
}
Have a look at the query library code. That looked reasonable to me at first. After all, the resolver named getBraintreeClientToken
is returning an object named BraintreeClientToken
, and it has a typename BraintreeClientToken
. Shouldn't that be what needs to be in the gql
query string?
[See answer below]
Well, that's the tweaky part. No. The gql
string can't be like that. It has to be:
QUERY LIBRARY
This is the correct code
const GETBRAINTREECLIENTTOKEN_QUERY = gql`
query ($localUserId: String!) {
getBraintreeClientToken(localUserId: $localUserId) {
clientToken
}
}
`;
The gql
query string makes no mention of the type being returned, and only lists the names of the fields that are being returned.
This is all perfectly reasonable, but it's not super-intuitive, and doesn't seem to be documented or explained very much. I'm posting it here for any others that may be looking for this info -- and for myself too if I need to look it up in the future.
WHY IT'S LIKE THAT
There's actually a really good reason why React is like this. It's foundational to React. One of the top benefits of React is that you can have a single endpoint that is capable of giving you every possible piece of data it has anything to do with -- but the client can use a query to get just the exact data it needs, by designing the Query
so that it specifies that data. This saves bandwidth and also, very importantly, keeps the backend developers from having to created a million different endpoints that deliver different sets of data back to the client. :)