9
votes

I am using AWS Appsync where I want to get a response from a successfully executed mutation. When I try my setup in the Appsync Graphql console I get a filled "data": { "mutateMeeting" } response: Appsync mutation

When I try the same in my react application I can see in the dynamodb database, that the mutations happen, but react-apollo does not return the mutation response. As you can see in the apollo dev tool, the "data": { "mutateMeeting" } is null :enter image description here

What am I missing?

The corresponding graphql schema reads:

input MeetingInput {
  id: String,
  start: String!,
  end: String!,
  agreements: [AgreementInput]!
}

type Meeting {
  id: String!
  start: String!
  end: String!
  agreements: [Agreement]
}

type Mutation { 
  mutateMeeting (
    companyId: String!,
    meeting: MeetingInput!
  ): Meeting!
}

the graphql-tag mutation reads:

import gql from 'graphql-tag'

export default gql`
  mutation mutateMeeting($companyId: String!, $meeting: MeetingInput!) {
    mutateMeeting(companyId: $companyId, meeting: $meeting) {
      id,
      start,
      end
    }
  }
`

and the react-apollo inklusion is given by:

import React, { Component } from 'react'
// antd
import { Spin } from 'antd'
// graphql
import { compose, graphql } from 'react-apollo'
import mutateMeeting from '../queries/mutateMeeting'

class MeetingStatus extends Component {
  componentDidMount() {
    const { mutateMeeting, meeting } = this.props
    console.log(meeting)
    const variables = {
      companyId: meeting.company.id,
      meeting: {
        start: meeting.start.toISOString(),
        end: meeting.end.toISOString(),
        agreements: meeting.agreements,
      }
    }
    console.log(variables)

    mutateMeeting({
      variables
    }).then(({data}) => console.log('got data', data))
    .catch(err => console.log(err))
  }

  render() {
    console.log(this.props)
    return <div>convocado</div>
  }
}

const MeetingStatusWithInfo = compose(
  graphql(mutateMeeting, { name: 'mutateMeeting' })
)(MeetingStatus)

export default (MeetingStatusWithInfo)

Appsync request

#set($uuid = $util.autoId())
#set($batchData = [])
#set( $meeting = ${context.arguments.meeting} )

## Company
#set( $meetingMap = {
  "PK" : $context.arguments.companyId,
  "SK" : "Meeting-$uuid",
  "start" : $meeting.start,
  "end" : $meeting.end
} )
$util.qr($batchData.add($util.dynamodb.toMapValues($meetingMap)))

## Meeting
$util.qr($meetingMap.put("PK", $meetingMap.SK))
$util.qr($batchData.add($util.dynamodb.toMapValues($meetingMap)))

## Agreements
#foreach($agreement in $meeting.agreements)
  #set( $agreementId = $util.autoId())
  #set( $agreementMap = {
    "PK" : $meetingMap.SK,
    "SK" : "Agreement-$agreementId",
    "name" : $agreement.name
  } )

  $util.qr($batchData.add($util.dynamodb.toMapValues($agreementMap)))
#end

{
  "version" : "2018-05-29",
  "operation" : "BatchPutItem",
  "tables": {
    "Vysae": $utils.toJson($batchData)
  }
}

Appsync response:

#set( $meeting = $context.result.data.Vysae[1] )
{
  "id": "$meeting.PK",
  "start": "$meeting.start",
  "end": "$meeting.end"
}
2
Can you please provide your resolvers? Because they might not properly be returning information with the expected property names in the right nesting, also, you might need to run an update, or updateQueries on the client after the data is returned.Benjamin Charais
I'll have a look at the update functionality and added the resolvers ;)Knowledge
@BenjaminCharais the from you mentioned update functions is for refreshing the cache. I want the ID, created by my request resolver, as a response from the mutation.Knowledge
Ah I misunderstood, but where are your resolvers, because if you are passing back the appropriate information from them, then the response from the mutation will appropriately map to the request. I can add an answer to.... dummy data out the flow of information.Benjamin Charais

2 Answers

1
votes

Looks like there's an open issue for this bug here. There's additional details in this original issue as well.

The user information in the SessionQuery will initially be cached and watched by the UserProfile component. When the UpdateAvatarMutation executes and returns, the query in the UserProfile component will receive empty data. Several others have also observed this behavior and all traced it to an imperfect overlap between the queried/cached fields and the fields returned on the mutation (in this example, email is missing from the User node on the mutation's returned results.

In other words, if you have a query that returns the same type of object, and there's a mismatch in the fields between the query and the mutation, it's possible you will end up with null data. It's not expected behavior, but if this is the underlying issue in this case, you could try to ensure the requested fields are the same for both your query and mutation.

1
votes

In my case, I had to write an update function in the mutation in order to get the data returned.

Try changing your mutation to this and look in the console to see if this changes anything:

mutateMeeting({
  variables,
  update: (proxy, {data: {mutateMeeting}}) => {
     console.log("Update: ", mutateMeeting);
  }
}).then(({data}) => console.log('got data', data))
  .catch(err => console.log(err))
}

The update function might be called a couple of times, but you should eventually see your data being returned as you expect it.

This is what worked for me. If you want, you can look at my question and see if that helps: React Apollo - Strange Effect When Making Mutation?