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

TypePolicies read returning nonexistent reference returns {} instead of query result #6844

Closed
dallonf opened this issue Aug 15, 2020 · 4 comments

Comments

@dallonf
Copy link

dallonf commented Aug 15, 2020

Intended outcome:

Was trying to follow the docs for cache redirects using field policy read functions. As an example:

const client = new ApolloClient({
  cache: new InMemoryCache({
    typePolicies: {
      Query: {
        fields: {
          personByIdWithTypePolicies: {
            read: (q, { args, toReference }) => {
              return toReference({
                __typename: "Person",
                id: args.id
              });
            }
          }
        }
      }
    }
  }),
  link
});

Actual outcome:

When the given ID does not correspond to an object that exists, the result given by the cache is {} instead of falling back to the query result of null.

For the given query (personById and personByIdWithTypePolicies are implemented exactly the same in the schema, but the latter uses the above type policy):

  query TestPeople {
    person: personById(id: "1") {
      id
      name
    }
    personWithTypePolicies: personByIdWithTypePolicies(id: "1") {
      id
      name
    }
    missingPerson: personById(id: "1000") {
      id
      name
    }
    missingPersonWithTypePolicies: personByIdWithTypePolicies(id: "1000") {
      id
      name
    }
  }

The result is:

{
    "person": {
      "__typename": "Person",
      "id": "1",
      "name": "John Smith"
    },
    "personWithTypePolicies": {
      "__typename": "Person",
      "id": "1",
      "name": "John Smith"
    },
    "missingPerson": null,
    "missingPersonWithTypePolicies": {}
}

I would expect the last item to be "missingPersonWithTypePolicies": null, because that's what came back from the schema.

How to reproduce the issue:

Here is a CodeSandbox repro containing and demonstrating the above examples: https://codesandbox.io/s/confident-swartz-psh7v

Versions

(This is from my local environment where I first detected the issue, not the CodeSandbox above. If it matters, I'm using Ubuntu within WSL 2 for Windows.)

  System:
    OS: Linux 4.19 Ubuntu 20.04 LTS (Focal Fossa)
  Binaries:
    Node: 14.5.0 - ~/.nvm/versions/node/v14.5.0/bin/node
    Yarn: 1.22.4 - ~/devroot/journaling/journaling-client/node_modules/.bin/yarn
    npm: 6.14.5 - ~/.nvm/versions/node/v14.5.0/bin/npm
  npmPackages:
    @apollo/client: ^3.1.3 => 3.1.3
    apollo: ^2.30.2 => 2.30.2
@benjamn
Copy link
Member

benjamn commented Aug 17, 2020

Often returning a dangling reference is fine, because it looks like missing data to the client, which can trigger a network request to fill in the missing data (depending on your FetchPolicy).

However, if you want to avoid returning a dangling reference from a read function, there's an options.canRead helper function (introduced by #6425) that you can use like so:

const client = new ApolloClient({
  cache: new InMemoryCache({
    typePolicies: {
      Query: {
        fields: {
          personByIdWithTypePolicies: {
            read: (q, { args, toReference, canRead }) => {
              const ref = toReference({
                __typename: "Person",
                id: args.id
              });
              return canRead(ref) ? ref : q;
            }
          }
        }
      }
    }
  }),
  link
});

Does that make sense / meet your needs?

@dallonf
Copy link
Author

dallonf commented Aug 17, 2020

This looks like a helpful workaround, but I believe the behavior is incorrect. In this case, it is making a network request for the missing data, but still returning the dangling reference via useQuery (with a result of {}).

@leethree
Copy link

leethree commented Feb 2, 2021

@benjamn I'm a bit confused about the workaround. Should we always check canRead if we want to do cache redirects? In what case does anyone want dangling references?

@eddiew
Copy link

eddiew commented Feb 9, 2021

I ran into this issue as well, and was able to resolve it with @benjamn's workaround. I saw that there was some discussion about checking canRead automatically in #6425 and I feel like if it isn't the default behavior, then apollo should at least provide a better debugging experience for when dangling references are returned. In my case the entire data object returned by useQuery was undefined, with no explanation as to why.

@hwillson hwillson closed this as completed May 5, 2021
@apollographql apollographql locked and limited conversation to collaborators May 5, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants