Intended outcome:
Updating the cache with a call to writeQuery to add a new item to the cache, but the new item is _missing some fields_ that are required by another query (which is using partialRefetch: true). It is expected that, given the query can no longer be satisfied by the cache, a refetch would be triggered.
Actual outcome:
No refetch is triggered, despite the cache only having a partial result for the query, resulting in a component that is out of sync with the cache.
How to reproduce the issue:
This is a contrived example that demonstrates the problem:
const orgsQuery = gql`
query {
member(id: "me") @client {
id
organizations {
id
# NOTE we have a 'name' here that is _not_ included when we do the writeQuery later.
# Having this 'name' field omitted from the writeQuery is what I would _expect_ to trigger
# a refetch of the component query, due to partial data
name
}
}
}
`;
const MemberStats: FunctionComponent = () => {
const { data, loading, error } = useQuery(orgsQuery, {
partialRefetch: true,
});
// This is not hit after we invoked the writeQuery
console.log('hook results', { data, loading, error });
const client = useApolloClient();
const onButtonClick = () => {
// This data is simulating a new organization being added to a member, but the new
// entry _only_ has an ID (it does not contain a name)
const newData = {
member: {
__typename: 'Member',
id: data.member.id,
organizations: data.member.organizations
.map((organization: { id: string }) => ({
id: organization.id,
__typename: 'Organization',
}))
.concat({
id: 'some-new-organization',
__typename: 'Organization',
}),
},
};
const queryToWrite = gql`
query {
member(id: "me") @client {
id
organizations {
id
}
}
}
`;
console.log('writing new data', { newData });
client.writeQuery({ query: queryToWrite, data: newData });
// Examining the cache shows that the new Organization was successfully added,
// and associated with the member
console.log('cache after write', { cache: client.extract() });
};
if (!data || loading || error) {
return null;
}
return (
<div>
{data.member.organizations.map(
(organization: { name: string; id: string }) => (
<div key={organization.id}>{organization.name}</div>
),
)}
<button onClick={onButtonClick}>OI</button>
</div>
);
};
At a high level we are:
id and name fields on the organizations belonging to the memberwriteQuery to add a _new_ organization to the member, but _only_ including the id field (no name field)Note: by adding returnPartialData: true the hook _does_ trigger a re-render with the partial organization:

But this is not what I want (I want complete data, which should be hydrated by refetching the query)
A re-render is _also_ triggered if we _do_ include the 'name' of the new organization in writeQuery (regardless of whether returnPartialData or partialRefetch are set to true)
This might be related to https://github.com/apollographql/react-apollo/issues/3605
It might also be related to https://github.com/apollographql/apollo-client/issues/5535.
Most helpful comment
Note: by adding
returnPartialData: truethe hook _does_ trigger a re-render with the partial organization:But this is not what I want (I want complete data, which should be hydrated by refetching the query)
A re-render is _also_ triggered if we _do_ include the 'name' of the new organization in
writeQuery(regardless of whetherreturnPartialDataorpartialRefetchare set totrue)