Apollo-client: Persistent data / Immutability

Created on 6 Nov 2017  ·  12Comments  ·  Source: apollographql/apollo-client

Intended outcome:

I have a chat app that shows messages in a view. We are using react-native with their FlatList implementation. If I send a new message it will be added to the list of messages in apollo store via fragment/query updaters. I expect it to be the only message that has changed in store. Thus only (re)-rendering that item.

Actual outcome:
After the message is added to apollo store, none of the messages are strictly equal anymore. This results in the entire chat-thread re-rendering, and horrible performance.

Is this issue resolved in a newer version of apollo? Maybe the new 2.0?

Version

🐞 bug

Most helpful comment

This will be fixed with 2.0.3 🌮

All 12 comments

@sondremare I don't know if this is fixed in the 2.0 though @jamesreggio has done some great work in ensuring ref equality. If not, can you upgrade, then create a small sample app with the incorrect behavior so I can write a test and fix it!

Thanks so much!

@jbaxleyiii Do you have a test-project with a mocked graphql backend that I can base it on?
EDIT: Looks like react-apollo has one I can use https://github.com/apollographql/react-apollo-error-template

@jbaxleyiii I have created a reproduction for the 1.4.2 version of apollo-client: https://github.com/sondremare/apollo-immutable/tree/apollo-v1.4.2

I have also tried to reproduce for v2 of apollo, but nothing happens when I do a writeQuery to the store. This code is located on master https://github.com/sondremare/apollo-immutable/tree/master.
Has writeQuery been removed? I went through the documentation, and found no evidence of that.

EDIT:
I investigated the in-memory cache, and noticed that the extra item is present in the store. But for some reason the query has been invalidated.

Hey @sondremare and @jbaxleyiii — I think this could be related to the problem I reported in #2360 where referential equality is being lost on most resultsets.

@sondremare, my temporary fix is to apply this patch to the apollo-client JS bundle directly. Depending on your version, it may not apply cleanly (and it may cause other side effects!), but for now it's getting us by:

*** ../node_modules/apollo-client/apollo.umd.js 2017-10-20 10:27:03.000000000 -0400
--- apollo.umd.js   2017-10-20 13:10:53.000000000 -0400
***************
*** 180,186 ****
                  }),
              };
          }
!         var _a = this.queryManager.getCurrentQueryResult(this, apolloUtilities.isEqual(this.variables, this.lastVariables)), data = _a.data, partial = _a.partial;
          var queryLoading = !queryStoreValue ||
              queryStoreValue.networkStatus === exports.NetworkStatus.loading;
          var loading = (this.options.fetchPolicy === 'network-only' && queryLoading) ||
--- 180,186 ----
                  }),
              };
          }
!         var _a = this.queryManager.getCurrentQueryResult(this, true), data = _a.data, partial = _a.partial;
          var queryLoading = !queryStoreValue ||
              queryStoreValue.networkStatus === exports.NetworkStatus.loading;
          var loading = (this.options.fetchPolicy === 'network-only' && queryLoading) ||

@jamesreggio Tried applying this patch, but still, when I writeQuery with another item, nothing happens rerendering-wise. The new item is never shown. @jbaxleyiii Do you have any idea why nothing happens?

@jbaxleyiii I have now added the workaround in https://github.com/apollographql/apollo-client/issues/2415 to broadcast changes after writeQuery is performed. The issue is reproducible in apollo-client 2.0.0 as well. Every single item is re-rendered (twice) when I add one item to the list.
Applying @jamesreggio's patch did not work either. The reproducible case can still be found here: https://github.com/sondremare/apollo-immutable/tree/master.

@jamesreggio This patch is introduce another problem with situation, when data, that query depends on, is modified while observableQuery is recycled during react component unmount. In recycled state it stops listening all broadcastQueries events, but stil contains all of instance properties, such as lastResult and lastVariables. Then, when component mounts again, this observableQuery is reused and lastResult, that not contains modified data, is returned from currentResult method call.

@SkReD, which version of apollo-client are you using?

I encountered a problem like the one you described (#2196), but @jbaxleyiii resolved it about a month ago. If you are still experiencing it on apollo-client 2.0.1, you should file another issue with a repro app. (They've made repros a lot easier with a template here: https://github.com/apollographql/react-apollo-error-template)

Also worth noting to all interest parties: my patch is not safe for production code. The only thing I'd use it for is to see if you're experiencing the problem I've filed over in #2360.

@jamesreggio apollo-client version 2.0.2. This issue happen only with checking this.lastVariables and this.variables. Because without it this.lastResult is never used and output is always recalculated and so it is always actual.

This will be fixed with 2.0.3 🌮

Great! Thanks :D

Was this page helpful?
0 / 5 - 0 ratings