I have mutation like this:
async updateGroceryList(_, { input: { grocery_list } }, { user }) {
return await Customer.findByIdUpdate(
user.roles.customer_id,
{ grocery_list },
{ 'new': true }
);
}
Mutation type:
updateGroceryList(input: updateGroceryListInput): Customer
input updateGroceryListInput {
grocery_list: [groceryItem]
}
input groceryItem {
item: String
quantity: String
}
I am calling my mutation in React like so:
// fields: [{ item: 'hello', quantity: 'world' }, {...}, ...]
this.props.mutate({ variables: { input: { grocery_list: fields } } })
.then(res => console.log(res))
.catch(err => console.log(`error sending the query: ${err}`));
And I define the mutation in the component like this:
const mutation = gql`
mutation updateGroceryList($input: updateGroceryListInput) {
updateGroceryList(input: $input) {
grocery_list {
item
quantity
}
}
}
`;
export default graphql(mutation)(Grocery);
But when I send the mutation, this is my request payload:
mutation updateGroceryList($input: updateGroceryListInput) {
updateGroceryList(input: $input) {
grocery_list {
item
quantity
__typename
}
__typename
}
}
Which throws this error:
Variable "$input" got invalid value {"grocery_list":[{"item":"hello","quantity":"world"},{"item":"bye","quantity":"world","__typename":"Grocery"}]}.鈫礗n field "grocery_list": In element #1: In field "__typename": Unknown field.
Yeah this is because the queries have __typename added to them to make data normalization work better, and when you pass that result through to the mutation it's still there.
Okay, that makes sense. How can I approach to solve this problem tho?
Should I add __typename when I define the input, like so?
input groceryItem {
item: String
quantity: String
__typename: String
}
No I think the best workaround right now is to strip out the typename before passing the object into the mutation.
But the moment I call the mutation, there is nothing to strip out:
// fields: [{ item: 'hello', quantity: 'world' }, {...}, ...]
this.props.mutate({ variables: { input: { grocery_list: fields } } })
.then(res => console.log(res))
.catch(err => console.log(`error sending the query: ${err}`));
Are you sure each item in fields doesn't have __typename in it? Unless you've explicitly stripped them out from the query results, they'll be in there.
Okay, I guess I didn't do it correctly then. Will try again.
Thanks for the help, @aryo @stubailo !
Any solution for this other than the workaround suggested by @stubailo ?
@omt66 You can set up you ApolloClient to not add the __typename to your query results, like so:
new ApolloClient({
addTypename: false,
networkInterface: createNetworkInterface({ uri: '/graphql' })
});
Thanks, that's much better. I will give it a try.
Whit react-apollo 2.x the use is a little bit different
```
new ApolloClient({
link: new HttpLink({ uri: 'http://localhost:4000' }),
cache: new InMemoryCache({
addTypename: false
}),
});
Before adding addTypename: false to your cache initializer, be aware that this solution will prevent you resolving fragments on unions and interfaces, as described in the Apollo documentation for IntrospectionFragmentMatcher.
Looks like in a recent update warnings were added:

So now this is becoming a real pain.
Why was this issue closed? Is this not a bug?
It would be nice to have a per-query option to strip out the __typenames. Something like:
import { graphql } from 'react-apollo';
import myQuery from './query.gql';
const MyComponent = () => { ... };
export default graphql(myQuery, {
addTypename: false
});
This could potentially provide cleaner data results to this.props.data and still be compatible with resolving fragments/interfaces.
@JonathanWbn I was under the impression that fields not requested by the component are not passed into the component?
Seems like stripping __typename from all query results with addTypename: false is too broad of a solution that could cause unintended consequences like @mikefowler pointed out.
Another solution could be to use filter with a fragment using graphql-anywhere.
<VoteButtons
entry={filter(VoteButtons.fragments.entry, entry)}
canVote={loggedIn}
/>
Where the fragment does not have __typename listed as an attribute.
https://github.com/apollographql/apollo-client/blob/master/docs/source/features/fragments.md#filtering-with-fragments
You can also use this package: https://www.npmjs.com/package/typename-monkey-patch which filters out __typename fields without doing addTypename: false and use graphql HOC as usual.
You just require the module somewhere near the entry point of your app.
const { __typename, ...otherAttributes } = someQueryResultObject
mutate(otherAttributes)
const { __typename, ...otherAttributes } = someQueryResultObject mutate(otherAttributes)
Thanks @speakingcode - that does the trick nicely.
const { __typename, ...otherAttributes } = someQueryResultObject mutate(otherAttributes)
@speakingcode doesn't really work if you have __typenames nested in your response.
Most helpful comment
Whit react-apollo 2.x the use is a little bit different
```
new ApolloClient({
link: new HttpLink({ uri: 'http://localhost:4000' }),
cache: new InMemoryCache({
addTypename: false
}),
});