question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Custom mutation processing (writeFragment) via update seems flaky.

See original GitHub issue

Intended outcome: writeFragment should update the cache.

Actual outcome: When processing mutations using the update option I get unstable results. Writing to the cache isn’t heavily documented, so I’m trying to understand the mechanism after days of trying to debug the issue.

My component’s props method returns null for it’s requested query item after it is mutated (not created – just mutated). But only after the first mutation. If I refresh the page, this doesn’t happen. And if I don’t call update and just refresh the query it doesn’t happen.

How to reproduce the issue: I don’t yet have a minimal repro app, but can repro it 100% in my current app.

  1. Create a component that queries for a parent item Project with child items Task.
  2. Create a new Task mutation and an update mutation adding the task to Project.tasks.
  3. Mutate the Task and the Project in separate mutations.

The Project’s HOC for it’s query returns null (even though it is in the cache). I have verified that after the mutation I can call proxy.readFragment and retrieve the correct Item (and that it exist in the devtool’s store). No network request is triggered – since I presume Apollo “thinks” the item is cached.

After issuing the mutations (Project + Task) this is what happens: 1). mutate.update is called and I write an updated Task and Project to the cache. 2). the network request for the batch happens (and completes successfully). 3). ‘Project.Query.options’ is called twice (multiple requests always seem to happen but why – redux chattiness?) 4). ‘Project.Query.props’ is called once with ‘loading=false’ and a null item. 5). 4 + 5 then happens again.

Even if I refresh the query after creating the fist mutations (i.e., new Task) then I get the same error when I change the Project and Task together. BUT if I refresh the query AFTER the second mutation the app is back in a functional state. IE this only happens for the first task that is created – which is the same code path as subsequent mutations.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:9 (5 by maintainers)

github_iconTop GitHub Comments

2reactions
dobesvcommented, Oct 19, 2017

I believe I am having a similar issue and may have a good idea of the cause.

What I am seeing is that if you use writeFragment or writeQuery to update the store, and some components have a query that is affected by the store, BUT the data you have written is missing some field(s) needed to satisfy those components’ query, they end up with no data and no network activity.

There is logic that refreshes all the component queries when the store is updated using writeQuery or writeFragment. As part of that it checks whether data is missing and sets a flag isMissing if so. When the data “disappears” what I see in the debugger is that isMissing is true and loading is false.

To elaborate, let us say we have two components A and B with these queries:

const queryA = gql`query A {
   widgets {
      purpose
      things {
          use
          lastUse
      }
   }
}`

queryB = gql`query B {
   widgets {
      things {
         use
      }
   }
}
`

Now, if I happen to use `writeQuery(queryB, ...)` to update the list of widgets, and there's no `lastUse` field provided in one of the things, `queryA` will report that data is missing, but never attempt to load that data.  In some cases, it doesn't even report any errors.

1reaction
helfercommented, Jul 4, 2017

Hey @richburdon thanks for the detailed description. I don’t have time to look into it, but I hope @jbaxleyiii will get to it at some point.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Mutations in Apollo Client - Apollo GraphQL Docs
This article demonstrates how to send updates to your GraphQL server with the useMutation hook. You'll also learn how to update the Apollo...
Read more >
Is it necessary to use 'writeFragment' while updating cache ...
@xadm, yeah I understand the purpose behind using an update function. My question was about the use of fragment instead of spreading the...
Read more >
apollo-cache-inmemory - Awesome JS
Prevent full reobservation of queries affected by optimistic mutation updates, while still delivering results from the cache. @benjamn in #6854. Improvements.
Read more >
Configuring InMemoryCache, or making updates to the cache ...
The way you update that data usually looks something like this: const [createTodo] = useMutation(CREATE_TODO, { update(cache, ...
Read more >
Managing State with React and Apollo Client | DoltHub Blog
There are three different ways we update fetched data after a mutation: using the refetchQueries option in the useMutation hook, ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found