CrustyRatFink
CrustyRatFink

Reputation: 534

Apollo Client client.readQuery returning null when data is in the cache

This must be user error, but I've got an app with a simple currentUser query that looks at a JWT for an id, looks it up, and returns the appropriate user.

I can look at devtools and see that it's in the cache as __ref:User:19

export const CURRENT_USER_QUERY = gql`
  query{
    currentUser {
      id
      fullName
      email
    }
  }
`

But in my component, when I do const { currentUser } = client.readQuery({ query: CURRENT_USER_QUERY }); it (intermittently) blows up because:

Cannot destructure property 'currentUser' of 'client.readQuery(...)' as it is null.

User:19 exists and is all the stuff I need. I hit reload, and that same page works.

I have my default error policy set to "all" in the client.

This is version 3.3.11 of the client. Chrome v88.04, for what that's worth. React 17.01.

Am I missing something here? Should that not return a value synchronously (and dependably) if that item's in the cache?

Is there a better way to deal with that situation? I'm trying to move this app away from storing things in redux or some context provider since it's already being handled by Apollo. Seems redundant to have that responsibility handled by a bunch of different things.

Upvotes: 14

Views: 11269

Answers (5)

freson
freson

Reputation: 96

You can extract object from cache by ID using fragments:

const data = client.readFragment({
    id: __TYPE_NAME + ':' + SOME_ID,
    fragment: gql`
      fragment CurrentItem on CartItem {
        id
        amount
      }
    `
  })

That is the simplest way to get a single cache entity without defining cache type Policies. Then you can interact with extracted object as you will:

  if (data) {
    client.cache.modify({
      id: client.cache.identify(data),
      fields: {
        amount(currentAmount) {
          return currentAmount + 1
        }
      }
    })
  } else {
    console.log("not in the cache...")
  }

Upvotes: 0

yaxx
yaxx

Reputation: 655

You need to pass the same variable with the same values you use when executing the mutation and in the same order

existingData = cache.readQuery({
   query: QUERY_NAME,
     variables: {
        x: mutationValue1,
        y: mutationValue2
        z: mutationValue3
   },
 });`

Upvotes: 0

Alia Anis
Alia Anis

Reputation: 1485

I was facing the same issue. I fixed it like this:

const existingData = cache.readQuery({
   query: GET_CONTRACT,
   variables: {
       ...variables, // fixed: passing the same reference to variables
   },
});

Upvotes: 6

Maksym Krugliachenko
Maksym Krugliachenko

Reputation: 323

The problem here can be in new variables or absence of variables. So the query was made with variables and you try to get it from the cache without. .readQuery from cache must be identical

Upvotes: 1

Anthony Peña
Anthony Peña

Reputation: 181

I was facing issues with .readQuery() last night. I was getting null returned everytime, though the logic was right. I was calling .readQuery() within a component I imported into my React page.

What ended up being my issue is that I was not updating the same query I made in the "parent" react page as the one in the component.

I don't know if this is the same problem you're running into, but I thought I'd leave this here for perpetuity and perspective.

Upvotes: 6

Related Questions