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

reactive variables not working after calling resetStore() #7664

Closed
pavelspichonak opened this issue Feb 6, 2021 · 11 comments · Fixed by #7696
Closed

reactive variables not working after calling resetStore() #7664

pavelspichonak opened this issue Feb 6, 2021 · 11 comments · Fixed by #7696
Assignees

Comments

@pavelspichonak
Copy link

pavelspichonak commented Feb 6, 2021

Intended outcome:

I have a reactive variable:
export const isLoggedIn = makeVar(false);

Here is client initialization:

export const graphqlClient = new ApolloClient({
  link: ApolloLink.from([authLink, logoutLink, httpLink]),
  cache: new InMemoryCache({
    typePolicies: {
      Query: {
        fields: {
          user: {
            read() {
              return {
                isLoggedIn: isLoggedIn(),
              };
            },
          }
        },
      },
    },
  }),
});

And I have a query:

export const GET_IS_USER_LOGGED_IN = gql`
  query GetIsUserLoggedIn {
    user @client {
      isLoggedIn
    }
  }
`;

I use this query in some place like this:

const { data: { user: { isLoggedIn } } } = useQuery(GET_IS_USER_LOGGED_IN);

Then I call graphqlClient.resetStore();

and after that I try to update reactive variable value like this isLoggedIn(true);

isLoggedIn should become true in this code:

const { data: { user: { isLoggedIn } } } = useQuery(GET_IS_USER_LOGGED_IN);

Actual outcome:

When you call graphqlClient.resetStore();

and after that you update reactive variable value like this:

isLoggedIn(true);

queries which use this reactive variable are not updated, for example this query still returns false in isLoggedIn property:

const { data: { user: { isLoggedIn } } } = useQuery(GET_IS_USER_LOGGED_IN);

But if I never use graphqlClient.resetStore(); and try to update reactive variable value like this isLoggedIn(true); all works great.

How to reproduce the issue:
Here is sandbox

First click click to reset store button and after that click click to change reactive variable value button. You will see that value is still false.

But if you just click click to change reactive variable value button, value will be changed to true.

Versions
System:
OS: macOS Mojave 10.14.6
Binaries:
Node: 15.4.0 - ~/.nvm/versions/node/v15.4.0/bin/node
Yarn: 1.22.10 - /usr/local/bin/yarn
npm: 7.0.15 - ~/.nvm/versions/node/v15.4.0/bin/npm
Browsers:
Chrome: 88.0.4324.150
Edge: 88.0.705.63
Firefox: 84.0.1
Safari: 13.0.5
npmPackages:
@apollo/client: ^3.3.8 => 3.3.8

@LittleCryingGirl
Copy link

got same issue today
@apollo/client: 3.3.8
OS: MacOS Big Sur 11.1
Node: v14.9.0
Yarn: 1.22.10
npm: 6.14.8
Firefox Developer edition 86.0b7

@pavelspichonak
Copy link
Author

pavelspichonak commented Feb 8, 2021

@jcreighton @benjamn could you please look at this issue? Looks like you were recently fixing issues related to reactive variables and this issue is also related to reactive variables.

Looks like if any active query contains reactive variables this query will not be updated when reactive variables values are changed. This happens after calling .resetStore(); or .clearStore(); methods.

And this issue happens after calling .resetStore(); as well. So maybe you could look at both of them?

Thanks a lot.

@jcreighton
Copy link
Contributor

@pavelspichonak It looks like your reproduction (thank you!) uses 3.3.7. I know you reported this happening with 3.3.8 but when I upgrade to that version in the reproduction, the reactive variable does update. Could you take a second look at that reproduction with 3.3.8?

@LittleCryingGirl I see you've also reported the issue with 3.3.8. If you're able to create a runnable reproduction, please do.

@pavelspichonak
Copy link
Author

@jcreighton yeah you are right. In the sandbox after updating to 3.3.8 it works. But in my project I use 3.3.8 and still have this issue. I will try to figure out why behavior in my project differs from behavior in the sandbox and will write again. Thanks.

@pavelspichonak
Copy link
Author

@benjamn @jcreighton guys after spending 3-4 hours finally I found the case when this issue happens. Here is a sandbox

Now apollo version is 3.3.8

If you click "click to logout" button - all works good and you will see true on the screen. But if you first click "click to reset store" button and after that click "click to logout" button - value is still false on the screen though reactive variable value is true.

@pavelspichonak
Copy link
Author

Now I use two queries and each query uses its own reactive variable. Also I use one query in the root component(App component) and the second query is used in nested component(Header component)

@vladimir-drachuk
Copy link

Hi @jcreighton @benjamn. Are there any updates related to this issue? Thank you.

@benjamn
Copy link
Member

benjamn commented Feb 12, 2021

@vladimir-drachuk We have a company-wide deadline today (peer reviews are due), but @jcreighton is actively working on fixing this.

@pavelspichonak
Copy link
Author

@benjamn @jcreighton thanks a lot for fixing this issue! Now it works. But may I ask you a question here? It is related to resetStore and reactive variables.

When user is logging out, I set reactive variable value to false like this isLoggedIn(false);

And there is query which uses this variable:

export const GET_IS_USER_LOGGED_IN = gql`
  query GetIsUserLoggedIn {
    user @client {
      isLoggedIn
    }
  }
`;

Some UI parts are rendered or not based on this query.

After setting isLoggedIn to false I call client.resetStore(). But when I call this method UI still have isLoggedIn with true value.

So I use setTimeout like this:


  isLoggedIn(false); // set reactive variable value to false

  setTimeout(() => {
    client.resetStore();
  });

It works. Now when client.resetStore() is executed UI already has isLoggedIn with false value. But I'm sure if it is a good to use setTiemout and if it is safe to use setTiemout or not? Thanks.

@benjamn
Copy link
Member

benjamn commented Feb 17, 2021

@pavelspichonak Thanks for following up. I wonder if the cache notification resulting from isLoggedIn(false) is not getting delivered to the client before client.resetStore() is called (when not using setTimeout).

Can you try forcing the broadcast like so?

isLoggedIn(false);
client["queryManager"].broadcastQueries();
client.resetStore();

TypeScript might complain about accessing the private client.queryManager property, but if this fixes your issue, I think we may be able to change resetStore so that it calls broadcastQueries internally before resetting the store. When I tried making that change just now, all of our existing tests still pass, so that's promising.

@brainkim brainkim assigned brainkim and unassigned brainkim Jun 22, 2021
@julianpetriv
Copy link

@benjamn hey, I have the same issue but with clearStore, it also stops UI from being rerendered. And your code
client["queryManager"].broadcastQueries(); really fixes it.
It would be nice if you make needed code changes to clearStore function.

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

Successfully merging a pull request may close this issue.

7 participants