Store same query with different filter separately in cache

Hello!
I’m using apollo client on React and I have a question.

I have a query fetchTasks that can be filtered by “Panel”
Panel.ADMIN
Panel.HISTORY
Panel.NORMAL

I have a page with 3 panels, each one querying with it’s filter.

My problem is that fetchTasks is stored in the cache as a single element.
I would like to have in my cache something like:
NormalTasks → Tasks filtered by NormalTasks
HistoryTasks → Tasks filtered by HistoryTasks
AdminTasks → Tasks filtered by AdminTasks

A possible solution I found is to stop using relayStylePagination() because I don’t have the args with this.
So i use

fetchTasks: {
        merge(
          existing = { edges: [], __typename: "" },
          incoming,
          { args, cache }
        ) {
          if (args && !args.after) {
            return incoming;
          }

          if (!incoming) return existing;
          const newEdges = incoming.edges;
          const pageInfo = incoming.pageInfo;
          const newTasks = {
            __typename: incoming.__typename,
            edges: [...existing.edges, ...newEdges],
            pageInfo,
          };

          return newTasks;
        },
      },

With that, I can can do something like that to get the desired tasks from the cache:

const tasks: FetchTasksQuery | null = client.readQuery({
query: fetchTasksQueryGql,
variables: {
  after: null,
  data: {
    filterBy: Panel.ADMIN,
  },
  first: 10,
},});

The problem is that with this technic I have to store the after value in a local state.
So I would prefer to store the Tasks in the cache based on the page argument.

Is it possible ? Thank you

@Blig I’m not sure if I fully follow your question, but is this something key arguments could help with?

@hwillson Yes I think it could !

If I do fetchTasks: relayStylePagination(["data"])
I’ll have all the data.
but fetchTasks: relayStylePagination(["page"]) doesn’t work.

I need to specify something like ["data filterBy page"] because page is inside filterBy and inside data.

Do you know how I could do that ?
I see that I can pass a KeyArgsFunction to relayStylePagination() that might help me to achieve that. But there is no documentation on KeyArgsFunction :confused:

Thank you for your help !

Great to hear it might work! We mention custom keyArgs functions a bit in the docs here (towards the bottom of that section), but for a better example of how they work I suggest checking out this test:

...
const cache = new InMemoryCache({
  typePolicies: {
    Thread: {
      keyFields: ["tid"],
      fields: {
        comments: {
          keyArgs(args, context) {
            expect(context.typename).toBe("Thread");
            expect(context.fieldName).toBe("comments");
            expect(context.field!.name.value).toBe("comments");
            expect(context.variables).toEqual({
              unused: "check me",
            });

            if (typeof args!.limit === "number") {
              if (typeof args!.offset === "number") {
                expect(args).toEqual({ offset: 0, limit: 2 });
                return ["offset", "limit"];
              }
              if (args!.beforeId) {
                expect(args).toEqual({ beforeId: "asdf", limit: 2 });
                return ["beforeId", "limit"];
              }
            }
          },
        },
      },
    },

    Comment: {
      keyFields: ["author", ["name"]],
    },
  },
});
...

Oh my !

Thank you very very much !
The thing I needed was fetchTasks: relayStylePagination(["data", ["filterBy", ["page"]]]),

Your example helped me a lot ! :rocket:

1 Like