首页 > 解决方案 > 删除带有突变的项目时如何正确修改Apollo缓存

问题描述

我不确定自己做错了什么,因为一切正常,但是每次运行DELETE_PHOTO突变时都会收到这个讨厌的错误消息:

替换用户对象的照片字段时,缓存数据可能会丢失。

我有用户对象,其中包含照片列表:

email: "test@test.fi"
fullname: "Test user"
id: "5f058ca0bf08318028019059"
isAdmin: true
photos:
    0:{"__ref":"Photo:5f44b37892f7b011ec491f25"}
    1:{"__ref":"Photo:5f44b37a92f7b011ec491f26"}
    2:{"__ref":"Photo:5f44b37d92f7b011ec491f27"}
    3:{"__ref":"Photo:5f44b38192f7b011ec491f28"}
    4:{"__ref":"Photo:5f44b38792f7b011ec491f2a"}
    5:{"__ref":"Photo:5f44b38992f7b011ec491f2b"}
    6:{"__ref":"Photo:5f44b38c92f7b011ec491f2c"}
    7:{"__ref":"Photo:5f44b38e92f7b011ec491f2d"}
    8:{"__ref":"Photo:5f44b39092f7b011ec491f2e"}
    9:{"__ref":"Photo:5f44b39292f7b011ec491f2f"}
    10:{"__ref":"Photo:5f44b39492f7b011ec491f30"}
    11:{"__ref":"Photo:5f44b39892f7b011ec491f31"}
    12:{"__ref":"Photo:5f44b39a92f7b011ec491f32"}
    13:{"__ref":"Photo:5f44b39d92f7b011ec491f33"}
    14:{"__ref":"Photo:5f44b3a092f7b011ec491f34"}
    15:{"__ref":"Photo:5f44b3a492f7b011ec491f35"}
    16:{"__ref":"Photo:5f44b3a792f7b011ec491f36"}
    17:{"__ref":"Photo:5f44b3aa92f7b011ec491f37"}
    18:{"__ref":"Photo:5f44b3ad92f7b011ec491f38"}
    19:{"__ref":"Photo:5f44b3af92f7b011ec491f39"}
    20:{"__ref":"Photo:5f44b3b292f7b011ec491f3a"}
    21:{"__ref":"Photo:5f44b3b592f7b011ec491f3b"}
    22:{"__ref":"Photo:5f44c5e192f7b011ec491f3c"}
    23:{"__ref":"Photo:5f453f1e479a7649e8191a04"}
username: "admin"

每个照片对象都是这样的:

dateAdded: "1598337912783"
description: null
filename: "images/851ca650-e69e-11ea-bdf1-eb9595fbd23e"
id: "5f44b37892f7b011ec491f25"
mainUrl: "https://firebasestorage.googleapis.com/..."
name: "2013-07-27 12-25-40 1479 (Canon EOS 40D)"
originalFilename: "2013-07-27 12-25-40 1479 (Canon EOS 40D).jpg"
thumbFilename: "images/851ca651-e69e-11ea-bdf1-eb9595fbd23e"
thumbUrl: "https://firebasestorage.googleapis.com/..."

获取用户对象的查询是:

export const ME = gql`
  query me {
    me {
      username,
      email,
      fullname,
      isAdmin,
      photos {
        mainUrl,
        thumbUrl,
        filename,
        thumbFilename,
        originalFilename,
        name,
        description,
        dateAdded,
        id
      },
      id
    }
  }
`;

删除照片的突变是:

export const DELETE_PHOTO = gql`
  mutation deletePhoto(
    $id: ID!
  ) {
      deletePhoto(
        id: $id
      ) {
        mainUrl,
        thumbUrl,
        filename,
        thumbFilename,
        originalFilename,
        name,
        description,
        dateAdded,
        id
      }
    }
`;

当我执行DELETE_PHOTO查询时,我得到这个关于已删除照片的对象作为响应:

deletePhoto:
    dateAdded: "1598337912783"
    description: null
    filename: "images/851ca650-e69e-11ea-bdf1-eb9595fbd23e"
    id: "5f44b37892f7b011ec491f25"
    mainUrl: "https://firebasestorage.googleapis.com/..."
    name: "2013-07-27 12-25-40 1479 (Canon EOS 40D)"
    originalFilename: "2013-07-27 12-25-40 1479 (Canon EOS 40D).jpg"
    thumbFilename: "images/851ca651-e69e-11ea-bdf1-eb9595fbd23e"
    thumbUrl: "https://firebasestorage.googleapis.com/..."
    __typename: "Photo"

然后我使用以下代码通过从用户对象的照片数组中删除该项目来更新 Apollo 缓存:

const [deletePhotoFromDb] = useMutation(DELETE_PHOTO, {
  update: (cache, response) => {
    const existingCache = cache.readQuery({ query: ME });
    if (existingCache) {
      const idToDelete = response.data.deletePhoto.id;
      const updatedPhotos = existingCache.me.photos.filter(p => p.id !== idToDelete);

      const updatedCache = {
        ...existingCache,
        me: {
          ...existingCache.me,
          photos: updatedPhotos
        }
      };

      cache.writeQuery({
        query: ME,
        data: updatedCache
      });
    }
  }
});

更新缓存有效,因为照片将立即从 React 的 UI 中删除。如果不更新缓存,照片将不会从 UI 中删除。

那么,我做错了什么来获取有关丢失缓存的错误消息?

Cache data may be lost when replacing the photos field of a User object.

To address this problem (which is not a bug in Apollo Client), define a custom merge function for the User.photos field, so InMemoryCache can safely merge these objects:

  existing: [{"__ref":"Photo:5f44b37a92f7b011ec491f26"},{"__ref":"Photo:5f44b37d92f7b011ec491f27"},{"__ref":"Photo:5f44b38192f7b011ec491f28"},{"__ref":"Photo:5f44b38792f7b011ec491f2a"},{"__ref":"Photo:5f44b38992f7b011ec491f2b"},{"__ref":"Photo:5f44b38c92f7b011ec491f2c"},{"__ref":"Photo:5f44b38e92f7b011ec491f2d"},{"__ref":"Photo:5f44b39092f7b011ec491f2e"},{"__ref":"Photo:5f44b39292f7b011ec491f2f"},{"__ref":"Photo:5f44b39492f7b011ec491f30"},{"__ref":"Photo:5f44b39892f7b011ec491f31"},{"__ref":"Photo:5f44b39a92f7b011ec491f32"},{"__ref":"Photo:5f44b39d92f7b011ec491f33"},{"__ref":"Photo:5f44b3a092f7b011ec491f34"},{"__ref":"Photo:5f44b3a492f7b011ec491f35"},{"__ref":"Photo:5f44b3a792f7b011ec491f36"},{"__ref":"Photo:5f44b3aa92f7b011ec491f37"},{"__ref":"Photo:5f44b3ad92f7b011ec491f38"},{"__ref":"Photo:5f44b3af92f7b011ec491f39"},{"__ref":"Photo:5f44b3b292f7b011ec491f3a"},{"__ref":"Photo:5f44b3b592f7b011ec491f3b"},{"__ref":"Photo:5f44c5e192f7b011ec491f3c"},{"__ref":"Photo:5f453f1e479a7649e8191a04"}]
  incoming: [{"__ref":"Photo:5f44b37a92f7b011ec491f26"},{"__ref":"Photo:5f44b37d92f7b011ec491f27"},{"__ref":"Photo:5f44b38192f7b011ec491f28"},{"__ref":"Photo:5f44b38792f7b011ec491f2a"},{"__ref":"Photo:5f44b38992f7b011ec491f2b"},{"__ref":"Photo:5f44b38c92f7b011ec491f2c"},{"__ref":"Photo:5f44b38e92f7b011ec491f2d"},{"__ref":"Photo:5f44b39092f7b011ec491f2e"},{"__ref":"Photo:5f44b39292f7b011ec491f2f"},{"__ref":"Photo:5f44b39492f7b011ec491f30"},{"__ref":"Photo:5f44b39892f7b011ec491f31"},{"__ref":"Photo:5f44b39a92f7b011ec491f32"},{"__ref":"Photo:5f44b39d92f7b011ec491f33"},{"__ref":"Photo:5f44b3a092f7b011ec491f34"},{"__ref":"Photo:5f44b3a492f7b011ec491f35"},{"__ref":"Photo:5f44b3a792f7b011ec491f36"},{"__ref":"Photo:5f44b3aa92f7b011ec491f37"},{"__ref":"Photo:5f44b3ad92f7b011ec491f38"},{"__ref":"Photo:5f44b3af92f7b011ec491f39"},{"__ref":"Photo:5f44b3b292f7b011ec491f3a"},{"__ref":"Photo:5f44b3b592f7b011ec491f3b"},{"__ref":"Photo:5f44c5e192f7b011ec491f3c"}]

标签: reactjscachinggraphqlapollo-client

解决方案


感谢xadm为我指出正确的评论方向。

我用以下内容替换了空的 InMemoryCache 对象,并且不再有警告消息:

const cache = new InMemoryCache({
  typePolicies: {
    User: {
      fields: {
        photos: {
          merge(existing = [], incoming: any[]) {
            return [...incoming];
          }
        }
      }
    }
  }
});

推荐阅读