Ответ относительно прост: в GraphQL нет универсального способа сообщить клиенту, что объект был удален. Давайте сначала сравним это с обновлением мутации. Представьте, что мы обновляем одно из заданий, которое у нас уже есть в нашем кэше. Сначала кеш (упрощенно, не совсем так, как выглядит внутри Apollo):
{
"Query": {
"jobs": ["Job:1", "Job:2"],
},
"Job:1": {
"__typename": "Job",
"id": 1,
"company": "Big Corp",
"title": "Sales Specialist"
},
"Job:2": {
"__typename": "Job",
"id": 2,
"company": "Big Corp",
"title": "GraphQL Expert"
}
}
Если Apollo теперь получает ответ от мутации обновления, которая выглядит следующим образом:
{
"data": {
"updateJob": {
"__typename": "Job",
"id": 2,
"company": "Big Corp",
"title": "GraphQL Unicorn"
}
}
}
Он может использовать функцию dataIdFromObject
, чтобы понять, что объект принадлежит ключу кэша "Job:2"
в нашем нормализованном кэше. Аполлон может предположить, что эта версия новее старой, и объединить ключи с предпочтением более нового результата. Наш кеш теперь выглядит следующим образом:
{
"Query": {
"jobs": ["Job:1", "Job:2"],
},
"Job:1": { ... },
"Job:2": {
"__typename": "Job",
"id": 2,
"company": "Big Corp",
"title": "GraphQL Unicorn" // updated!
}
}
Тогда запрос "jobs"
автоматически обновится с новым заданием, поскольку он просто ссылается на задание и не хранит сам объект. Большой! Но теперь сравните результат с функцией удаления:
{
"data": {
"deleteJob": {
"returning": {
"id": 2,
}
}
}
}
Результатом этого запроса может быть что угодно. Аполлон не может знать, что вы только что удалили работу с определенным идентификатором. Возможно, если бы в спецификации GraphQL было что-то вроде магического «__isDeleted» и мы получили бы что-то вроде:
{
"data": {
"deleteJob": {
"__typename": "Job",
"__isDeleted": true,
"id": 2,
}
}
}
}
Мы могли бы дать нашей реализации кэша подсказку, что сущности с __isDeleted: true
должны быть удалены из всех ссылокзапросы. Но, к сожалению, этого не существует. Это не так уж плохо, но мы можем либо использовать refetchQuery
для запуска повторного получения другого запроса, либо мы можем обновить другой запрос вручную :
const deleteJob = useMutation(DELETE_JOB, {
update(store, response) {
const data = store.readQuery({ query: GET_JOBS });
data.jobs = data.jobs.filter(job => job.id !== response.deleteJob.returning.id);
store.writeQuery({ query: GET_JOBS, data });
}
});