Cache.modify inserts fragments to all queries regardless of query variable

Hi there, I’ve been using Apollo for a while, but still haven’t figured out the below problem…

The query I’m executing is the below in multiple components with different source id.

export const GET_SOURCE_DETAILS_CONDITIONAL: TypedDocumentNode<{
  sourceDetails: sourceDetailExtended[];
}> = gql`
  ${SOURCE_DETAIL_FIELDS}
  query GET_SOURCE_DETAILS_CONDITIONAL($where: sourceDetails_bool_exp!) {
    sourceDetails(where: $where) {
      ...SourceDetailFields
    }
  }
`;

const { data } = useQuery(GET_SOURCE_DETAILS_CONDITIONAL, {
    variables: {
      where: {
        sourceId: {
          _eq: source.id,
        },
      },
    },
  });

And after I execute an insert mutation, call cache.modify, I get the problem where the added items gets attached to all the queries (GET_SOURCE_DETAILS_CONDITIONAL).

update(cache, { data }) {
            let insertedSoureDetails = (data.insert_sourceDetails?.returning ||
              []) as sourceDetail[];

            if (data.insert_sources_one) {
              insertedSoureDetails.concat(data.insert_sources_one);
            }

            cache.modify({
              fields: {
                sourceDetails(existing = []) {
                  const newSourceRefs = insertedSoureDetails.map(sd => {
                    return cache.writeFragment({
                      data: sd,
                      fragment: SOURCE_DETAIL_FIELDS,
                      fragmentName: "SourceDetailFields",
                    });
                  });
                  return [...existing, ...newSourceRefs];
                },
              },
            });
          },

above is the logic I use to update cache and below is the fragment for the query

export const SOURCE_DETAIL_CORE_FIELDS = gql`
  fragment SourceDetailCoreFields on sourceDetails {
    id
    sourceId
    companyId
    name
  }
`;

export const SOURCE_DETAIL_FIELDS = gql`
  ${SOURCE_DETAIL_CORE_FIELDS}
  fragment SourceDetailFields on sourceDetails {
    ...SourceDetailCoreFields
    source {
      id
      name
      isSourceCompany
      companyId
    }
    company {
      id
      name
    }
  }
`;

At the moment I have to do this in order to filter incorrectly added data

  const sourceDetails = (data?.sourceDetails || []).filter(
    sd => sd.sourceId == source.id
  );

However, as you can expect, once the where filter gets complicated, it’ll be prone to too many mistakes and is surly an unnecessary step.

I tried implementing keyargs, keyfields in the typePolicies in various ways but none seem to help with my situation…

If anyone can help and shed some light on it, I’d appreciate it dearly.

You probably need to pass an id argument to writeFragment here. Alternatively, you could make sure that the data (and fragment) you are passing in here contain a __typename, that could also work out. Unfortunately I’m not exactly sure what the shape of data you are writing here is exactly.

Hi there,

First, thanks for your input and suggestion.
I’ve tried manually adding id: sourceDetails:${sd.id}`` to the writeFragment method and also checking that the refs contatin _typename.
Manually adding the id unfortunately didn’t do the trick and upon checking the refs returned from the writeFragment, they all contain the __typename correctly.

I also tried changing the query to the below however with no avail.

const GET_SOURCE_DETAILS_FOR_SOURCE: TypedDocumentNode<{
  sourceDetails: sourceDetail[];
}> = gql`
  ${SOURCE_DETAIL_FIELDS}
  query GET_SOURCE_DETAILS_FOR_SOURCE($id: Int!) {
    sourceDetails(where: { sourceId: { _eq: $id } }) {
      ...SourceDetailFields
    }
  }
`;

And below is the shape of the data for sourceDetail

sourceDetails:69
__typename:"sourceDetails"
id:69
sourceId:21
companyId:6
name:null
__ref:"sources:21"
__ref:"companies:6"

Would there be any other information that I can put up to better understand the source of problem…?

UPDATE

I was able to get my desired result by using cache.updateQuery method rather than using the cache.modify.
I’ve tried adding variables to cache.writeFragment method inside cache.modify, but that also didn’t work.
I think I still need to understand deeper mechs behind apollo but honestly, dealing with cache is HARD…
I’m leaving my code below for anyone who might run in to the same problem.

        cache.updateQuery(
          {
            query: GET_SOURCE_DETAILS_CONDITIONAL,
            variables: {
              where: {
                sourceId: {
                  _eq: source.id,
                },
              },
            },
          },
          data => {
            const existing = data?.sourceDetails || [];
            return {
              sourceDetails: existing.concat(insertedSoureDetails),
            };
          }
        );