【问题标题】:Apollo client mutation with writeQuery not triggering UI update带有 writeQuery 的 Apollo 客户端突变未触发 UI 更新
【发布时间】:2020-03-13 13:14:56
【问题描述】:

我有一个突变来创建一个新的卡片对象,我希望它应该在更新后添加到用户界面中。缓存、Apollo Chrome 工具和控制台日志记录反映了更改,但 UI 并非没有手动重新加载。

 const [createCard, { loading, error }] = useMutation(CREATE_CARD, {
    update(cache, { data: { createCard } }) {
      let localData = cache.readQuery({
        query: CARDS_QUERY,
        variables: { id: deckId }
      });

      localData.deck.cards = [...localData.deck.cards, createCard];
;

  client.writeQuery({
    query: CARDS_QUERY,
    variables: { id: parseInt(localData.deck.id, 10) },
    data: { ...localData }
  });

我已将 cache.writeQuery 更改为 client.writeQuery,但这并没有解决问题。

作为参考,这是我正在运行的查询...

const CARDS_QUERY = gql`
  query CardsQuery($id: ID!) {
    deck(id: $id) {
      id
      deckName
      user {
        id
      }
      cards {
        id
        front
        back
        pictureName
        pictureUrl
        createdAt
      }
    }
    toggleDeleteSuccess @client
  }
`;

【问题讨论】:

  • 您如何在应用程序的其他地方请求该查询 -- useQuery?是否为该查询设置了 no-cache 策略?
  • 我更新了一个我终于遇到的解决方案,显然深度克隆数据对象是触发UI更新的常用方法。我使用了一个相当基本的 useQuery 来显示卡片组中的闪存卡列表,并且我使用了一个定制的弹出模式组件来添加、编辑或删除卡片。我的获取策略是默认的。编辑和删除更新可以很好地更新缓存和 UI,而无需使用重新获取,它是将卡片添加到我遇到麻烦的现有卡组中。

标签: apollo react-apollo apollo-client


【解决方案1】:

好的,终于遇到了很长的Github thread 讨论他们针对同一问题的解决方案。最终对我有用的解决方案是深度克隆数据对象(我个人使用 Lodash cloneDeep),在将变异的数据对象传递给 cache.writeQuery 之后,它终于更新了 UI。最终,考虑到缓存反映了更改,似乎仍然应该有一种方法来触发 UI 更新。

这是之后,查看我之前的原始问题......

const [createCard, { loading, error }] = useMutation(CREATE_CARD, {
  update(cache, { data: { createCard } }) {
    const localData = cloneDeep(  // Lodash cloneDeep to make a fresh object
      cache.readQuery({
        query: CARDS_QUERY,
        variables: { id: deckId }
      })
    );

    localData.deck.cards = [...localData.deck.cards, createCard];  //Push the mutation to the object

    cache.writeQuery({
      query: CARDS_QUERY,
      variables: { id: localData.deck.id },
      data: { ...localData }  // Cloning ultimately triggers the UI update since writeQuery now sees a new object.
    });
  },
});

【讨论】:

  • 当你改变一些对象时,你应该做浅拷贝,而不是深拷贝。您不需要克隆所有内容。
【解决方案2】:

我在没有 cloneDeep 方法的情况下管理了相同的结果。只需使用扩展运算符就解决了我的问题。

const update = (cache, {data}) => {
  const queryData = cache.readQuery({query: USER_QUERY})
  const cartItemId = data.cartItem.id
  queryData.me.cart = queryData.me.cart.filter(v => v.id !== cartItemId)
  cache.writeQuery({query: USER_QUERY, data: {...queryData}})
}

希望这对其他人有所帮助。

【讨论】:

    猜你喜欢
    • 2019-12-05
    • 2021-09-16
    • 1970-01-01
    • 2018-12-19
    • 2018-02-07
    • 2020-03-09
    • 2020-02-03
    • 2018-09-03
    • 2019-11-14
    相关资源
    最近更新 更多