I try to make a GraphQl mutation using apollo graphQl client.
This makes an error 500
when the mutation variables contains ___typename
properties (which obviously don't exist in the graphQl schema).
To fix that it is possible to set addTypename: false
in the graphQl client config:
const graphqlClient = new ApolloClient({
link: authLink.concat(httpLink),
cache: new InMemoryCache({
addTypename: false
})
})
Now the mutation almost works…
But there is a new error: You're using fragments in your queries, but either don't have the addTypename: true option set in Apollo Client, or you are trying to write a fragment to the store without the __typename. Please turn on the addTypename option and include __typename when writing fragments so that Apollo Client can accurately match fragments.
So how should the graphQl client be configured to handle mutations?
for now I use a cleanup function found here:
const removeTypename = (value) => {
if (value === null || value === undefined) {
return value;
} else if (Array.isArray(value)) {
return value.map(v => removeTypename(v));
} else if (typeof value === 'object') {
const newObj = {};
Object.keys(value).forEach(key => {
if (key !== '__typename') {
newObj[key] = removeTypename(value[key]);
}
});
return newObj;
}
return value;
};
but it feels hacky. Is there something built-in graphql client?
I try to make a GraphQl mutation using apollo graphQl client.
This makes an error 500
when the mutation variables contains ___typename
properties (which obviously don't exist in the graphQl schema).
To fix that it is possible to set addTypename: false
in the graphQl client config:
const graphqlClient = new ApolloClient({
link: authLink.concat(httpLink),
cache: new InMemoryCache({
addTypename: false
})
})
Now the mutation almost works…
But there is a new error: You're using fragments in your queries, but either don't have the addTypename: true option set in Apollo Client, or you are trying to write a fragment to the store without the __typename. Please turn on the addTypename option and include __typename when writing fragments so that Apollo Client can accurately match fragments.
So how should the graphQl client be configured to handle mutations?
for now I use a cleanup function found here:
const removeTypename = (value) => {
if (value === null || value === undefined) {
return value;
} else if (Array.isArray(value)) {
return value.map(v => removeTypename(v));
} else if (typeof value === 'object') {
const newObj = {};
Object.keys(value).forEach(key => {
if (key !== '__typename') {
newObj[key] = removeTypename(value[key]);
}
});
return newObj;
}
return value;
};
but it feels hacky. Is there something built-in graphql client?
Share Improve this question edited Oct 12, 2018 at 23:50 François Romain asked Oct 12, 2018 at 19:55 François RomainFrançois Romain 14.4k17 gold badges92 silver badges128 bronze badges 2-
Are you trying to use the data returned by another query as one of your mutation's variables? Otherwise, it's not clear when the variables passed to a mutation would contain a
__typename
field. – Daniel Rearden Commented Oct 12, 2018 at 22:50 -
yes exactly. The
___typename
were added from a previous query – François Romain Commented Oct 12, 2018 at 23:47
2 Answers
Reset to default 4So, thanks to @Daniel Rearden idea and this ment, I use a custom apollo link to strip typenames from mutations variables:
const omitTypename = (key, value) => {
return key === '__typename' ? undefined : value
}
const omitTypenameLink = new ApolloLink((operation, forward) => {
if (operation.variables) {
operation.variables = JSON.parse(
JSON.stringify(operation.variables),
omitTypename
)
}
return forward(operation)
})
Then use it with the other links like so:
const link = ApolloLink.from([authLink, omitTypenameLink, httpLink])
const cache = new InMemoryCache()
const graphqlClient = new ApolloClient({
link,
cache
})
Taking the value of some query and then plugging it mutation as a variable is an atypical scenario, so there's not an easy solve for what you're trying to do. While you can configure your client instance to omit the __typename
field from your results, an object's __typename
(along with its id
or _id
) are used as cache keys -- omitting it is going to cause some unexpected behavior if it doesn't outright break things.
By far the best approach to this is just to manipulate the query result before passing it in as a variable. I think something like this should do the trick:
function stripTypenames (value) {
if (Array.isArray(value)) {
return value.map(stripTypenames)
} else if (value !== null && typeof(value) === "object") {
const newObject = {}
for (const property in value) {
if (property !== '__typename') {
newObject[property] = stripTypenames(value[property])
}
}
return newObject
} else {
return value
}
}
On a side note, unless you're using client-side data (i.e. apollo-link-state
) it's hard to image a situation where you would fetch some data from the server and then have to feed that same data into a mutation. If the data exists on the server already, it should be sufficient to pass in an id for it and retrieve it server-side. If you're having to jump through these sort of hoops, it may be an indicator that the API itself needs to change.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744172893a4561619.html
评论列表(0条)