question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Cannot update a field in cache that has not been queried yet

See original GitHub issue

Intended outcome:

Consider an example API with following schema:

type Country {
  code: ID!
  name: String!
  states: [State!]!
}

type State {
  code: ID!
  name: String!
  country: Country!
}

I want to add another state to Country in the cache. Thus I wrote the following function:

const addState = () => {
    client.cache.modify({
      id: `Country:{"code":"US"}`,
      fields: {
        states(existingStateRefs = [], { canRead }) {
          console.log("ADDING STATE!");
          const newStateRef = client.cache.writeFragment({
            data: {
              __typename: "State",
              code: "Seoul",
              name: "Seoul",
              country: { __ref: `Country:{"code":"US"}` }
            },
            fragment: gql`
              fragment NewState on State {
                code
                name
                country
              }
            `
          });

          console.log("NEW REF", canRead(newStateRef));

          return canRead(newStateRef)
            ? [...existingStateRefs, newStateRef]
            : existingStateRefs;
        }
      }
    });
  };

When I have queried the following query, everything works fine.

const COUNTRY_QUERY = gql`
  query country($code: ID!) {
    country(code: $code) {
      code
      name
      states {
          code
          name
       }
    }
  }
`;

Actual outcome:

However, if I query the following query, which does not have states field,

const COUNTRY_QUERY = gql`
  query country($code: ID!) {
    country(code: $code) {
      code
      name
    }
  }
`;

The client.cache.modify.fields’s states function does not even executed without any error. I expected the state function to be executed with existingStateRef argument of undefined.

How to reproduce the issue:

I’ve reproduced the issue on codesandbox https://codesandbox.io/s/apollo-client-cache-error-reproduction-zx62j?file=/src/App.js:582-701

Versions

System:
    OS: macOS 10.15.6
  Binaries:
    Node: 14.15.1 - /usr/local/bin/node
    Yarn: 1.22.10 - /usr/local/bin/yarn
    npm: 6.14.8 - /usr/local/bin/npm
  Browsers:
    Chrome: 89.0.4389.82
    Safari: 14.0
  npmPackages:
    @apollo/client: ^3.3.7 => 3.3.7 
    apollo-upload-client: ^14.1.3 => 14.1.3 

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

4reactions
benjamncommented, Mar 11, 2021

@SeungsuKim When you’re using writeFragment, you don’t have to worry about { __ref } reference objects (like you do when you’re using cache.modify), so here’s how I would simplify that code:

const chatMessagesFragment = gql`
  fragment Messages on Chat {
    messages {
      id
    }
  }
`;

const newMessageId = cache.identify(newMessage);

const chatCache = cache.readFragment<{ messages: { id: string }[] }>({
  id: newMessageId,
  fragment: chatMessagesFragment,
});

cache.writeFragment({
  id: newMessageId,
  fragment: chatMessagesFragment,
  data: {
    messages: [
      ...(chatCache ? chatCache.messages : []),
      newMessage,
    ],
  },
});

In case you haven’t seen it already, here’s the documentation we have for cache.modify. I agree it could be more explicit about the inability to add new fields (cc @StephenBarlow). Although cache.modify doesn’t warn when nothing is modified, it does return a boolean to indicate whether any modifications happened, in case that’s useful.

0reactions
hwillsoncommented, May 26, 2021

It doesn’t sound like there is an outstanding issue here, so closing. Thanks!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Reading and writing data to the cache - Apollo GraphQL Docs
To update cached data safely, see Combining reads and writes. If the cache is missing data for any of the query's fields, readQuery...
Read more >
useMutation updates cache but does not re-render ... - GitHub
Intended outcome: I am querying for one object (Object A) and checking for the existence of one of its fields (Object B) in...
Read more >
How to update the Apollo Client's cache after a mutation
writeQuery({ query, data }); }, },})(MyComponent);. That's cool, but what happens if the query has not yet been fetched, so is not in...
Read more >
Update the apollo cache without calling the graphql server ...
If either cache.writeQuery or your typePolicies merge causes an active query field to be missing from the cache, it will result in a...
Read more >
Cache Updates | urql Documentation
A query's result is represented as a graph, which can also be understood as a ... mutations and subscriptions still write and update...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found