aws-mobile-appsync-sdk-js icon indicating copy to clipboard operation
aws-mobile-appsync-sdk-js copied to clipboard

buildMutation not working properly

Open flybayer opened this issue 6 years ago • 11 comments
trafficstars

I'm trying to use buildMutation, and it doesn't seem to be working correctly. I'm also confused by the discrepancy between docs and source.

The Amplify API docs say to do this:

  const result = await client.mutate(buildMutation(client,
    gql(createStudent),
    {
      inputType: gql(CreateStudentInput),
      variables
    },
    (_variables) => [ gql(listStudents) ],
    'Student'
  ));

but by looking at the source code it looks like I should do this:

  const result = await client.mutate(buildMutation(
      client,
      gql(createStudent),
      variables,
      gql(listStudents),
      'Student'
  ))

Here's what happens using the second code sample

  1. I initiate create on a Student named 'Bob'

  2. (In another component) The listStudents query returns an empty data.listStudents while the mutation is in flight.

  3. Once the server returns success, then listStudents returns a full data.listStudents including the new record.

  4. Console shows a bunch of errors like

 Missing field bookMaps in {
  "__typename": "Student",
  "id": "30128546-4592-4833-852f-1bdddba858ce",
  "firstName": "Bob"
My `createStudent` mutation
export const createStudent = `mutation CreateStudent($input: CreateStudentInput!) {
  createStudent(input: $input) {
    id
    firstName
    lastName
    birthdate
    curriculumMaps {
      items {
        id
      }
      nextToken
    }
    bookMaps {
      items {
        id
      }
      nextToken
    }
    resourceMaps {
      items {
        id
      }
      nextToken
    }
    summaryMaps {
      items {
        id
      }
      nextToken
    }
  }
}`

My `listStudents` query
export const listStudents = `query ListStudents(
  $filter: ModelStudentFilterInput
  $limit: Int
  $nextToken: String
) {
  listStudents(filter: $filter, limit: $limit, nextToken: $nextToken) {
    items {
      id
      firstName
      lastName
      birthdate
      curriculumMaps {
        nextToken
      }
      bookMaps {
        nextToken
      }
      resourceMaps {
        nextToken
      }
      summaryMaps {
        nextToken
      }
    }
    nextToken
  }
}
`

Versions

"aws-appsync": "1.7.1",
"aws-appsync-react": "1.2.6",

flybayer avatar Jan 31 '19 14:01 flybayer

Hi @flybayer

The source code you linked is not the one for the aws-appsync version you are using, this is the correct one, it should be in sync with the docs (let me know if it isn't)

https://github.com/awslabs/aws-mobile-appsync-sdk-js/blob/aws-appsync%401.7.1/packages/aws-appsync/src/helpers/offline.ts#L272

manueliglesias avatar Feb 01 '19 01:02 manueliglesias

What the world... not sure how I got hold of that old link!

Here's what happens using the code from the docs:

  1. I don't get the empty data.listStudents while the request is in flight, but I do still get the Missing field bookMaps in ... errors.

  2. Cache is never updated, even after successful API response. When offline, the mutation returns an optimistic response success, but the cache is not updated. Also when going back online, the request is never sent to the server.

Lastly, the buildMutation API as documented is extremely confusing. Is there any way the API can be simplified? At the very, very least, it would help to have it fully documented (like what is (_variables) => [ gql(listStudents) ] ??)

Thanks

Edited 2/4/18: cache is actually never updated

flybayer avatar Feb 01 '19 14:02 flybayer

At the very, very least, it would help to have it fully documented (like what is (_variables) => [ gql(listStudents) ] ??)

I'm struggling with this as well. The opportunistic part doesn't seem to do anything. It's unfortunate that there doesn't seem to be a full (accurate up to date) example.

Also the docs point to this which only lists "graphqlMutation" specifically for react, with no mention of buildMutation at all.

4ext avatar Feb 02 '19 14:02 4ext

And just for the record, I need to use buildMutation instead of graphqlMutation because graphqlMutation doesn't work with react hooks.

flybayer avatar Feb 03 '19 16:02 flybayer

Update: buildMutation is never updating the cache, even after a successful API response. I thought this was working earlier, but I forgot to comment out my refetch() while testing this.

flybayer avatar Feb 04 '19 22:02 flybayer

I wonder if this is related to #364? Delete mutation executes, but the cache is not updated.

ffxsam avatar Feb 22 '19 23:02 ffxsam

Update: buildMutation is never updating the cache, even after a successful API response. I thought this was working earlier, but I forgot to comment out my refetch() while testing this.

I made the same experience. it updates the cache when i write do not use Arrays in the _variables

Like: ` var tmp = buildMutation( client, gql(createTodo), { inputType: gql(createTodoInput), variables: { input: { name: todoName.value } } }, _variables => gql(listTodos), "Todo" ); const result = await client.mutate(tmp);

`

StefanV85 avatar Mar 18 '19 09:03 StefanV85

For me it also works only if I provide a single query to update - the documentation is quite misleading. Plus it fails if item is missing any of the optional fields (in my case it was an array from @connection directive that was not yet created).

It takes way too much effort and guessing-game to make it work, especially that using helpers is the recommended way to use the mutation - and by the way, the AWS Amplify documentation still points to https://github.com/awslabs/aws-mobile-appsync-sdk-js/blob/master/OFFLINE_HELPERS.md, 5 months after opening this ticket...

@elorzafe any outcome from the investigation? Maybe a simple example (in Typescript if possible) and doc update would be sufficient?

kjlis avatar Jun 15 '19 19:06 kjlis

I made the same experience. it updates the cache when i write do not use Arrays in the _variables

It doesn't update the cache with array or without array. Without array example

const response = await client.mutate(buildMutation(client, gql(createTodo), 
      {
        inputType: gql(`input CreateTodoInput {
          id: ID
          name: String!
        }`),
        variables,
      },
      (_variables: any) => gql(listTodos), 'Todo'))

With Array example

const response = await client.mutate(buildMutation(client, gql(createTodo), 
      {
        inputType: gql(`input CreateTodoInput {
          id: ID
          name: String!
        }`),
        variables,
      },
      (_variables: any) => [gql(listTodos)], 'Todo'))

apoorvmote avatar Nov 06 '19 11:11 apoorvmote

Any update here? It's been a year and a half since this issue has any comments. And today, I'm having the same problems, the documentation is the same and I can't find any solution.

santi8194 avatar Jun 05 '20 18:06 santi8194

Another 18 months on, still an issue.

PeteDuncanson avatar Jan 17 '22 13:01 PeteDuncanson