Search code examples
javascriptgraphqlapolloapollo-client

Apollo Client and filtered queries


I'm making an app for birdwatchers. When birdwatches see a bird, they record a sighting. I have a query for a feed of all birdwatchers sightings:

import { gql } from "@apollo/client";

export const GET_SIGHTINGS = gql`
  query Sightings($first: Int, $after: String) {
    sightings(first: $first, after: $after) {
      pageInfo {
        endCursor
      }
    edges {
      node {
        id
        location
        note
        seenAt
        mapImage
        images {
          id
          url
        }
        user {
          id
          name
          emoji
        }
        bird {
          id
          commonName
        }
      }
    }
  }
}
`;

and this works great. Now i want to have a seperate feed for an individual birdwatchers sightings. (this query is working fine on the server):

import { gql } from "@apollo/client";

export const MY_SIGHTINGS = gql`
  query MySightings($first: Int, $after: String, $userId: ID) {
    mySightings: sightings(first: $first, after: $after, userId: $userId) @connection(key: "sightings", filter: ["userId"]) {
      pageInfo {
        endCursor
      }
      edges {
        node {
          id
          location
          note
          seenAt
          mapImage
          images {
            id
            url
          }
          user {
            id
            name
            emoji
          }
          bird {
            id
            commonName
          }
        }
      }
    }
  }
`;

This works fine the first time the filtered query was run, however once the main feed component is rendered, the individual feed is now full of everyones sightings. How do I get the cache to descriminate between the two queries? The @connection directive sounded like it would be the trick but apparently not


Solution

  • I'm using the Relay Specification for my API which means that my 'collections' are objects rather than arrays. This means I need to set a specific Type Policy to get pagination to work. This also unfortunately also breaks Apollos automatic handling of query params. Turns out I need to add userId to the keyargs section of my type policy:

    const cache = new InMemoryCache({
      typePolicies: {
        Query: {
          fields: {
            sightings: {
              keyArgs: ["userId"],          
              merge(existing, incoming, { args }) {
                if (args && !args.after) {
                  return incoming;
                }
                if (!existing) {
                  return incoming;
                }
                const edges = unionBy("node.__ref", existing.edges, incoming.edges);
                return { ...incoming, edges };
              },
            },
          },
        },
      },
    });