Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apollo response from mutation is undefined

I use Apollo-client 2.3.5 to to add some data and then update the local cache. The mutation works but the return from the mutation is undefined in the Apollo client, but the response in the network request is correct.

So I have two querys, one for fetching all bookings and one for adding a booking.

const addBookingGQL = gql`
mutation createBooking($ref: String, $title: String, $description: String, $status: String!){
    createBooking(ref: $ref, title: $title, description: $description, status: $status){
        id
        ref
        title
        description
        status
    }


   }
`;

const GET_BOOKINGS = gql`
  query {
    bookings {
      id
      ref
      title
      status
      description
    }
  }
`;

I then have a Apollo mutation wrapper where I use the update prop. addBooking should be populated with the result of the mutation, but unfortunately it is undefined.

<Mutation 
                mutation={addBookingGQL}
                update={(cache, { data: { addBooking } }) => {
                    const { bookings } = cache.readQuery({ query: GET_BOOKINGS });
                    console.log("cache read query bookings: ", cache);
                    cache.writeQuery({
                        query: GET_BOOKINGS,
                        data: { bookings: bookings.concat([addBooking]) }
                    });
                }}
            >
                {(addBooking, { loading, error }) => (
                    <div>
                        <Button 
                            onClick={() => {
                                addBooking({
                                    variables: {
                                        ref: this.state.ref,
                                        title: this.state.title,
                                        description: this.state.description,
                                        status: "BOOK_BOX",
                                    }
                                });

                                this.handleClose();

                            }} 
                            color="primary">
                            Create
                        </Button>
                        {loading && <p>Loading...</p>}
                        {error && <p>Error :( Please try again</p>}
                    </div>
                )}

            </Mutation>

This results in following error in the console:

    errorHandling.js:7 Error: Error writing result to store for query:
 {
  bookings {
    id
    ref
    title
    status
    description
    __typename
  }
}

Cannot read property '__typename' of undefined
    at Object.defaultDataIdFromObject [as dataIdFromObject] (inMemoryCache.js:33)
    at writeToStore.js:347
    at Array.map (<anonymous>)
    at processArrayValue (writeToStore.js:337)
    at writeFieldToStore (writeToStore.js:244)
    at writeToStore.js:120
    at Array.forEach (<anonymous>)
    at writeSelectionSetToStore (writeToStore.js:113)
    at writeResultToStore (writeToStore.js:91)
    at InMemoryCache.webpackJsonp../node_modules/apollo-cache-inmemory/lib/inMemoryCache.js.InMemoryCache.write (inMemoryCache.js:96)

I tried running the mutation in the Graphiql dev tool receiving the expected response:

{
  "data": {
    "createBooking": {
      "id": "bd954579-144b-41b4-9c76-5e3c176fe66a",
      "ref": "test",
      "title": "test",
      "description": "test",
      "status": "test"
    }
  }
}

Last I looked at the actual response from the graphql server:

{
 "data":{
  "createBooking":{
   "id":"6f5ed8df-1c4c-4039-ae59-6a8c0f86a0f6",
   "ref":"test",
   "title":"test",
   "description":"test",
   "status":"BOOK_BOX",
   "__typename":"BookingType"
  }
 }
}

If i use the Apollo dev tool for chrome i can see that the new data is actually appended to the cache, which confuses me.

like image 978
Peter Savnik Avatar asked Jul 11 '18 17:07

Peter Savnik


Video Answer


1 Answers

Have you checked out this apollo issue comment?

The suggestion is to create an apollo-link that parses the operation variables and omits keys containing __typename:

function createOmitTypenameLink() {
  return new ApolloLink((operation, forward) => {
    if (operation.variables) {
      operation.variables = JSON.parse(JSON.stringify(operation.variables), omitTypename)
    }

    return forward(operation)
  })
}

function omitTypename(key, value) {
  return key === '__typename' ? undefined : value
}
like image 155
Peter Avatar answered Oct 05 '22 22:10

Peter