14

I'm completely stuck on an Apollo problem, for which I've opened a GitHub issue and had zero response on.

I'm calling an Apollo mutation, using optimisticResponse. The way it's supposed to work, as I understand it, is that update() gets called twice: first with the optimistic data, then again with the actual data coming in from the network.

But for some reason, my code is not working like this. I'm getting two update() calls, both with the optimistic data.

Here's a repo that demonstrates this behavior: https://github.com/ffxsam/apollo-update-bug

  1. yarn && yarn dev
  2. Open in browser, open console
  3. Enter some text and hit enter
  4. Repeat above
  5. Notice the error in the console about duplicate keys. This is happening because the temporary ID "??" is not being replaced with the real UUID (optional) You can open Vue DevTools if available and inspect the data to see it's incorrect
Uddhav P. Gautam
  • 7,362
  • 3
  • 47
  • 64
ffxsam
  • 26,428
  • 32
  • 94
  • 144
  • Can you see if this PR, merged today, resolves your issue: https://github.com/awslabs/aws-mobile-appsync-sdk-js/pull/43 – Richard Feb 27 '18 at 05:13
  • I know this isn't really a "solution" but it looks like the `aws-appsync@deepdish` tag has a fix (at least it seems to work for me now. I don't believe that this is a stable branch, so buyer beware in production, but it's working for me as of now. Source: https://github.com/awslabs/aws-mobile-appsync-sdk-js/issues/170 – John Landgrave Jul 10 '18 at 17:41

1 Answers1

24

I was doing some digging and I think I found the source of the problem. Unfortunately, I don't have a solution.

In short, the problem might be with a network link called OfflineLink that is used by aws-appsync.

Explanation

aws-appsync has an ApolloLink called OfflineLink that intervenes with the request function.

What happens is something like this:

  1. you call $apollo.mutate(...)
  2. ApolloClient.QueryManager initializes the mutation that triggers your update the first time with the optimistic response. That is happening inside ApolloClient data store, markMutationInit calls markMutationResult that calls your update.
  3. The graphql operation executes and reaches the OfflineLink in the network chain.
  4. OfflineLink creates a new observer and dispatches the mutation info as an action.
  5. The next line of OfflineLink calls the observer's next function with the optimisticResponse as if it was the execution result!
  6. This triggers your update the second time with the result which is actually the optimisticResponse.
  7. OfflineLink calls the observer's complete which resolves your promise.
  8. console.log('done!'...

Meanwhile, OfflineLink prevents the original mutation from even sending the request, and a new mutation is generated and sent with the options you've given it.

Tal Z
  • 3,170
  • 17
  • 30
  • This was totally the issue. THANK YOU. – ffxsam Feb 27 '18 at 00:58
  • Can you check the latest PR that was merged and see if the issue still exists? You can find it here: https://github.com/awslabs/aws-mobile-appsync-sdk-js/pull/43 – Richard Feb 27 '18 at 05:12
  • 1
    Wonderful. This is mainly causing me a problem in create mutation - my app temporarily shows duplicate data. It was a simple workaround for me to check if the data already exists and only showing optimisticResponse for the first time. Update query's server response won't update the data but the data is re-requested from the server immediately that anyway. Hopefully this issue gets fixed soon! – Lindlof Mar 15 '18 at 20:23