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

Query does not trigger a rerender after a clearStore #8995

Open
MartijnHols opened this issue Nov 1, 2021 · 4 comments
Open

Query does not trigger a rerender after a clearStore #8995

MartijnHols opened this issue Nov 1, 2021 · 4 comments
Assignees
Labels
🏓 awaiting-team-response requires input from the apollo team

Comments

@MartijnHols
Copy link

MartijnHols commented Nov 1, 2021

When checking the user's logged in state I do a me { id } query. This returns null if the user is logged out. I then show the login page, and if a user logs in using the login mutations they get a "me" object with the data. During the login process, I clear the store and using an onClearStore, write the new "me" query data.

This has stopped working in 3.4.16 after working in 3.4.15. I think this was caused by a change by @benjamn, specifically: https://github.com/apollographql/apollo-client/pull/8873/files#diff-b156746d5b1aac290dd27cf54cf4713d7ffbe0fce30e5a0dc6114d7b3529ea28R487

Intended outcome:
The query triggers a re-render, updating the component as it did in 3.4.13.

Actual outcome:
The query data is stale until something else triggers a re-render.

How to reproduce the issue:

  1. Run query for user login state (returns null)
  2. Then execute
  const removeWriter = apolloClient.onClearStore(async () => {
    if (me !== undefined) {
      await apolloClient.writeQuery({
        query,
        data: {
          me, // this has actual data now
        },
      })
    }
  })
  await apolloClient.clearStore()
  removeWriter()
  1. the query in 1 does not trigger a rerender

Versions
I have tested the following versions:

  • 3.4.13: works
  • 3.4.14: broken
  • 3.4.15: works
  • 3.4.16: broken again

ps. I feel like I reported this before, but I can't remember if I actually did and couldn't find another issue. I definitely didn't report it for the latest version though.

@benjamn
Copy link
Member

benjamn commented Nov 1, 2021

@MartijnHols My first instinct is to steer you towards client.resetStore, which restarts queries after clearing the store, possibly closer to the behavior you need here… unless you're using client.clearStore for a specific reason?

For example, maybe you're using client.clearStore instead of client.resetStore because you specifically don't want any queries besides the query { me { id }} query to be restarted?

If that's the case, then I think there might be a missing middle ground between client.resetStore and client.clearStore, and a new/combined API could enable selectively restarting only specific queries, using a syntax similar to the include array for client.refetchQueries.

@benjamn benjamn self-assigned this Nov 1, 2021
@MartijnHols
Copy link
Author

MartijnHols commented Nov 1, 2021

First of all, I went with client.cache which is the middleground I needed. I forgot why I needed onClearStore in the past. I think in a lot older version it used to refetch the me querybefore mywriteQuery` applied to the store. In the current version it doesn't appear to be doing this, so my code now works with using the cache directly.

Indeed I don't want to restart the queries. When I do, the me query is refetched despite me already having that data and writing it in the store. This is especially an issue when you have many different me queries requesting different fields (although I use a custom batching solution so I only fire one query nowadays). In addition other components that only work in certain conditions won't have been unmounted yet, refetching and triggering lots of unnecessary errors. This most commonly is when logging out, but can also occur when logging in. I'll explain what I do to clarify why this happens.

I have a hook useIsLoggedIn that executes the me query to check if the user is logged in (it's a lot more complicated, but that's the gist). To simplify my code, I have put lots of other hooks that need to execute when the user is logged in components that are only rendered when this is true. So my App component looks something like this:

const isLoggedIn = useIsLoggedIn()

return (
  <Providers>
    <Router />

    {/* Set the `user` context in Sentry */}
    {isLoggedIn && <SentryUser />}
    {/* Activate subscriptions (which also rely on data from queries) */}
    {isLoggedIn && <Notifications />}
    {isLoggedIn && <UserUpdated />}
  </Providers>
)

Most of the queries within the isLoggedIn conditions can only be called if the user is logged in or they will throw an UNAUTHORIZED error. If I do a resetStore these queries are refetched before they're unmounted by the changing useIsLoggedIn hook. I actually don't need anything to refetch after clearing the store, as my writeQuery takes care of everything that I need so long as existing queries rerender correctly.

@llamadeus
Copy link

I'm also having troubles resetting/clearing the store after logout. Refetching queries, which happens when you use resetStore, when you know they will result in an authorization error seems not very useful to me. Using clearStore on the other hand discards any watches, so manual writes to the cache won't update the UI.

@MartijnHols I've added my opinion to the discussion which lead to PR #8873. You may want to follow the discussion.

@happyfloat
Copy link

I'm facing a similar issue after upgrading from 3.3.21 to 3.4.16.

Previously this imperative query would fetch and store data and re-render my useQuery hook with 'cache-only'. Now the hook doesn't trigger a re-render anymore. It sill has the correct data if something else triggers a new render.

const result = await client.query<
    GetAuthUserQuery,
    GetAuthUserQueryVariables
  >({
    errorPolicy: 'ignore',
    query: GetAuthUserDocument,
    variables: {userId},
  });

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🏓 awaiting-team-response requires input from the apollo team
Projects
None yet
Development

No branches or pull requests

5 participants