Cache data may be lost when replacing the my field of a Query object
Asked Answered
I

3

13

this my code

const NewVerificationCode = () => {
  const { loading, error, data = {}, refetch } = useQuery(CONFIRMATION_CODE, {
    skip: true,
    onError: (err) => {},
  });
  console.log(loading, error, data);

  if (loading || error) {
    return <ErrorLoadingHandler {...{ loading, error }} />;
  }

  return (
    <form
      onSubmit={(e) => {
        refetch();
        e.preventDefault();
      }}
    >
      <div>
        <button type="submit" className="signUpbutton">
          {"Send the message again"}
        </button>
      </div>
    </form>
  );
};

const CONFIRMATION_CODE = gql`
  query {
    my {
      sendNewTokenForConfirmation
    }
  }
`;

when i make a request i get a warning

Cache data may be lost when replacing the my field of a Query object.

To address this problem (which is not a bug in Apollo Client), either ensure all >objects of type My have IDs, or define a custom merge function for the Query.my >field, so InMemoryCache can safely merge these objects existing:

    {"__typename":"My","getUser{"__typename":"User","email":"[email protected]"}}

incoming: {"__typename":"My","sendNewTokenForConfirmation":"SUCCESS"}

For more information about these options, please refer to the documentation:

I followed the links.

I read the documentation and realized that the problem is in the apollo client cache (typePolicies).

But how should I solve this problem I just can't figure out.

What should i write in typePolicies to get rid of the warning ?.

Idiocy answered 15/8, 2020 at 7:18 Comment(0)
N
13

You may need to return an id for Apollo to uniquely identify that object in the cache. I think this issue is similar to yours: link

const CONFIRMATION_CODE = gql`
  query {
    my {
      id
      sendNewTokenForConfirmation
    }
  }
`;
Natation answered 16/8, 2020 at 2:49 Comment(1)
If I understood you correctly, my should return id.I tried it but that doesn't work either.Idiocy
C
5

Every object should return id, _id or alternatively a custom id field (https://www.apollographql.com/docs/react/caching/cache-configuration) for automatic merges to function.

const cache = new InMemoryCache({
  typePolicies: {
    Product: {
      keyFields: ["custom-id-field"],
    },
  },
});

(!)People often forget that cache operations require the same variables used for the initial query (!)

Mutation Sample (adding a purchase):

update(cache, { data: NewPurchase } }) => {
  let productCache = cache.readQuery({
    query: productQuery,
    variables: {
      id: productId
    }
  })
 
  cache.writeQuery({
    query: productQuery,
    variables: { id: productId },
    data: {
      Product: {
        ...productCache.Product,
        purchases: productCache.Product.purchases.concat(NewPurchase)
      }
    }
  });
 };
}

(Important: Each Purchase also requires it's own individual id that needs to be returned)

Calendre answered 26/1, 2021 at 16:7 Comment(2)
What to do if the object was deleted?Roasting
you can use a filter to remove the object: purchases: productCache.Product.purchases.filter(purchase => purchase.id != RemovedPurchased.id)Calendre
P
1

Locate the file where you create ApolloClient and provide a merge method for your field:

 cache: new InMemoryCache({
    typePolicies: {
        Query: {
            fields: {
                my: {
                    merge(existing, incoming) {
                        return incoming;
                    }
                },
            },
        },
    }
}),

See this post for more info

Papain answered 15/2 at 13:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.