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

refetch never updates cache read function values #7994

Closed
mohit497 opened this issue Apr 16, 2021 · 2 comments
Closed

refetch never updates cache read function values #7994

mohit497 opened this issue Apr 16, 2021 · 2 comments

Comments

@mohit497
Copy link

mohit497 commented Apr 16, 2021

When try to access the client side data in query , the refetch query always returns the cached value, for example if you have client read function taking values form localStorage , it will cache the first value and never return the latest

Intended outcome:

Refetch should call the read function again and get latest client state values

Actual outcome:

Right now the refetch values are cached and updated values are not returned
How to reproduce the issue:

  • Add a client property in a query and setup read function for it
  • No update the source for read function
  • Now refetch the query and you can still see last values in the results
  • can try setting the policy to - network-only still same result

Versions

System:
OS: Linux 5.8 Ubuntu 20.04.2 LTS (Focal Fossa)
Binaries:
Node: 10.19.0 - /usr/bin/node
npm: 6.14.4 - /usr/bin/npm
Browsers:
Firefox: 87.0
npmPackages:
@apollo/client: 3.4.0-beta.23 => 3.4.0-beta.23

@benjamn
Copy link
Member

benjamn commented Apr 16, 2021

@mohit497 InMemoryCache attempts to reuse unchanged result objects (since #3394, before AC3), to keep repeated reads as cheap as possible.

One expectation that comes with this extra layer of caching is that the InMemoryCache must be notified somehow when the underlying data sources have changed. In other words, your read function isn't getting called because the cache is reusing a previously-computed result object that contains the field in question.

A good way to keep the cache informed about changes in the underlying data is with a reactive variable:

import { InMemoryCache, makeVar } from "@apollo/client";

const localStorageVar = makeVar(localStorage.getItem(key));

function setLocalStorage(newValue) {
  localStorage.setItem(key, newValue);
  localStorageVar(newValue);
}

const cache = new InMemoryCache({
  typePolicies: {
    YourType: {
      fields: {
        someField: {
          read() {
            // Accessing the reactive variable's value in this context creates a
            // dependency between the current query and localStorageVar, which
            // allows notifying the cache later, if/when the variable changes.
            return localStorageVar();
          },
        },
      },
    },
  },
});

Another way to cause read functions to rerun is to cache.evict the field in question:

cache.evict({
  id: cache.identify({ __typename: "YourType", id }),
  fieldName: "someField",
})

If you don't want the field to temporarily disappear from the cache, a more advanced version of the cache.evict trick is to use cache.modify and INVALIDATE:

cache.modify({
  id: cache.identify({ __typename: "YourType", id }),
  fields: {
    someField(value, { INVALIDATE }) {
      return INVALIDATE;
    },
  },
})

Any of these approaches should cause read functions to rerun for queries that consume the YourType.someField field.

@hwillson
Copy link
Member

@mohit497 let us know if #7994 (comment) doesn't clarify things. Thanks!

@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.
Projects
None yet
Development

No branches or pull requests

4 participants