Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

optimisticResponse freezes / lags UI #6201

Closed
brotzky opened this issue Apr 27, 2020 · 6 comments
Closed

optimisticResponse freezes / lags UI #6201

brotzky opened this issue Apr 27, 2020 · 6 comments

Comments

@brotzky
Copy link

brotzky commented Apr 27, 2020

I'm not 100% sure this is a bug, but whenever we use optimisticResponse on a mutation hook the UI will freeze for ~500-1000ms. Removing the optimisticResponse will render the UI updates without any lag -- the feedback is instant.

For example, a user selects an option from a dropdown and the dropdown will only close 500ms after they've selected. If we remove the optimisticResponse the dropdown closes immediately.

I was wondering if anyone's had this issue and if there's a workaround? We want to update the UI as the user selects an option but can't because of the lag.

Here's an example of of a mutation with an optmisticResponse that would delay an UI updates

updateUser({
  variables: {
    userID: user.id,
    name: newName,
  },
  optimisticResponse: {
    __typename: 'Mutation',
    updateUser: {
      ...user,
      name: newName,
    },
  },
  update: updateUserCache,
})

--

"apollo-cache-inmemory": "^1.6.5",
"apollo-client": "^2.6.8",
"apollo-link": "^1.2.13",
"apollo-link-batch-http": "^1.2.13",
"apollo-link-context": "^1.0.19",
"apollo-link-error": "^1.1.12",
"apollo-link-http": "^1.5.16",
"apollo-link-ws": "^1.0.19",
"apollo-utilities": "^1.3.3",

"react": "^16.13.1",
"react-dom": "^16.13.1",
@klaussner
Copy link

klaussner commented Apr 28, 2020

Can you share two performance profiles/flame graphs that show the time between the click and the finished rendering (with and without optimisticResponse)? Also, are you using shouldComponentUpdate or React.memo in a React subtree that renders data of a query that's affected by the updateUserCache function?

@brotzky
Copy link
Author

brotzky commented Apr 29, 2020

Yes, using useMemo to the affected cache updates. I added more and double checked the dep arrays to make sure it was ok.
Here are some graphs, looks like about 130ms for the optimistic cache update

Here it is with optimistic:

Screen Shot on 2020-04-28 at 17-44-07
Screen Shot 2020-04-28 at 5 44 55 PM

And without optimistic

Screen Shot 2020-04-28 at 5 48 04 PM

@klaussner
Copy link

The cache updates take much less time than the 500-1000 ms you mentioned above, so the performance problem may be caused by the re-rendering that's happening after the update.

The reason why I was asking about shouldComponentUpdate and React.memo is that the InMemoryCache returns a new JavaScript object for every object in the query result after an optimisticResponse is applied, even for objects that didn't change. Therefore, useMemo and other React performance optimizations that use === to compare query results don't work for optimistic responses (see issue #4141). Do you think this could be the reason for the UI freeze you are seeing?

@brotzky
Copy link
Author

brotzky commented May 1, 2020

I've been digging into this and I think it's because we have one large query that's a combination of a few queries and the single object gets quite large because of that. I'm starting to break it down into smaller queries and seeing if updating the cache will be improved this way. So when we write to the cache it updates a smaller portion.
The memo stuff had a small improvement, but not enough to solve the problem.
Thanks for all the help @klaussner. I'm going to keep digging into this and report back.

@brotzky
Copy link
Author

brotzky commented May 9, 2020

We were able to get around this through various changes to our app. The largest change was breaking down one massive query we had into lots of smaller queries. We should've done this in the beginning but were fairly new to GraphQL when we started.
By breaking down the cache into smaller pieces I'm guessing each update now only updates a small portion of the cache instead of a huge object.
We also doubled down on React.useMemo which seems to have helped with components that would receive updates but didn't need to re-render.
Lastly we trimmed down some views and tried our best to keep the DOM as light as possible.

With those three updates things are feeling a lot faster and we haven't run into massive lag issues.

@brotzky brotzky closed this as completed May 9, 2020
@BitFlippa27
Copy link

BitFlippa27 commented Apr 14, 2021

Hey brotzky,
i got the same problem right now.
Can i ask how you broke down your massive query ?

In my example i got a Query FETCH_CITIES_QUERY which gets me around 25 000 entries of cities.
I assume that Optimistic UI doesn't work well with such large data sets. Do you know why ?
The thing is when removing Optimistic UI, the UI gets suprisingly updated immediately, even though it has to update the cache too. As far as i know, the only difference with Optimistic UI is, that it runs the update function twice, once it updates the cache with the optimistic response and then secondly when the real response from the server comes back. Maybe its slow because it reads and writes to the cache twice ?

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 15, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants