Closed SeungsuKim closed 3 years ago
@SeungsuKim This is one of the downsides of cache.modify
: it can only modify existing field values, so you can't use it to add new fields.
Try using a combination of readFragment
and writeFragment
instead?
const idUS = cache.identify({
__typename: "Country",
code: "US",
});
const dataUS = cache.readFragment({ id: idUS, fragment }));
const newStateRef = cache.writeFragment({ ... });
cache.writeFragment({
id: idUS,
fragment,
data: {
...dataUS,
states: [
...dataUS.states,
newStateRef,
],
},
});
If you need the canRead
helper, you should be able to use cache.store.canRead
.
Happy to answer questions if you get stuck on anything!
@benjamn I've solved the problem as follows. I'm trying to add a new Message
data received by subscription to a messages
field of type Chat
. Is there any more elegant and concise way to do this?
const chatCache = cache.readFragment<{ messages: { id: string }[] }>({
id: `Chat:${newMessage.chatId}`,
fragment: gql`
fragment ExistingMessages on Chat {
messages {
id
}
}
`,
});
cache.writeFragment({
id: `Chat:${newMessage.chatId}`,
fragment: gql`
fragment NewMessages on Chat {
messages
}
`,
data: {
messages: [
...(chatCache?.messages.map(message => ({
__ref: `Message:${message.id}`,
})) || []),
{ __ref: `Message:${newMessage.id}` },
],
},
});
@benjamn Also, if the cache.modify
function is intended to not modify non-existing fields, I think it should be documented and throw a warning when such cases happen. I took so much time to figure out that cache.modify
does not work with non-existing fields. Is there any documentation about this behavior?
@SeungsuKim When you're using writeFragment
, you don't have to worry about { __ref }
reference objects (like you do when you're using cache.modify
), so here's how I would simplify that code:
const chatMessagesFragment = gql`
fragment Messages on Chat {
messages {
id
}
}
`;
const newMessageId = cache.identify(newMessage);
const chatCache = cache.readFragment<{ messages: { id: string }[] }>({
id: newMessageId,
fragment: chatMessagesFragment,
});
cache.writeFragment({
id: newMessageId,
fragment: chatMessagesFragment,
data: {
messages: [
...(chatCache ? chatCache.messages : []),
newMessage,
],
},
});
In case you haven't seen it already, here's the documentation we have for cache.modify
. I agree it could be more explicit about the inability to add new fields (cc @StephenBarlow). Although cache.modify
doesn't warn when nothing is modified, it does return a boolean to indicate whether any modifications happened, in case that's useful.
It doesn't sound like there is an outstanding issue here, so closing. Thanks!
Intended outcome:
Consider an example API with following schema:
I want to add another state to
Country
in the cache. Thus I wrote the following function:When I have queried the following query, everything works fine.
Actual outcome:
However, if I query the following query, which does not have
states
field,The
client.cache.modify.fields
'sstates
function does not even executed without any error. I expected thestate
function to be executed withexistingStateRef
argument ofundefined
.How to reproduce the issue:
I've reproduced the issue on codesandbox https://codesandbox.io/s/apollo-client-cache-error-reproduction-zx62j?file=/src/App.js:582-701
Versions