如果查询尚未缓存,如何在突变后安全地更新Apollo客户端缓存

时间:2018-04-01 22:42:12

标签: reactjs caching apollo react-apollo

TL; DR:

如果如果要更新的查询尚未运行并已缓存(即在页面重新加载后),我如何安全地更新Apollo客户端缓存?

问题

Apollo文档不清楚如何更新(安全或不安全)从未运行过的缓存查询(因此没有要修改的缓存数据)。尝试在没有缓存数据的查询上使用writeQuery会引发错误,显然不会更新查询。

  • 在每次致电try...catch期间使用writeQuery
    • 这真的不是一种有效的方法,但可能是唯一的方法吗?
    • 发生的其他错误呢?
  • 以某种方式为查询缓存设置默认状态
    • 似乎需要做很多工作来支持应用的初始状态,这可能会阻止查询运行?

我目前唯一的想法是围绕不同的查询更新调用try...catch,但这似乎是额外的工作。不仅如此,我还是可能会忽略与已经存在的查询无关的实际错误。

实施例

我有两个组件,一个用于列出用户的个人消息,另一个用于用户草稿列表。即使所有草稿个人消息,但我使用两个不同的查询来提高效率,因为用户可能总是比发送的消息少得多。

正常使用应用程序时(例如,在导航时加载所有查询)一切正常。要创建草稿,我需要转到Drafts.jsx(加载草稿查询,重要!)并单击按钮创建草稿。在创建草稿时,我运行下面看到的update函数(需要更新两个查询,因为它们的内部参数不同)。 “草稿”查询的缓存更新按预期工作,因为查询已经执行并且数据存储在缓存中。但是,由于我从未访问过MyMessages页面,因此“MyMessages”查询失败并引发错误。

代码

我的消息查询(在MyMessages.jsx

const RECEIVED_MESSAGES_QUERY = gql`
  query GetGroup($groupSlug: String!) {
    groupEdge(groupSlug: $groupSlug) {
      node {
        id
        name
        slug
        allMessages(author: true) {
          edges {
            node {
              id
              status
              subject
              preview
            }
          }
        }
      }
    }
  }
`;

草稿查询(在Drafts.jsx中):

const DRAFT_MESSAGES_QUERY = gql`
  query GetGroup($groupSlug: String!) {
    groupEdge(groupSlug: $groupSlug) {
      node {
        id
        name
        slug
        allMessages(author: true, includeStatus: ["draft"]) {
          edges {
            node {
              id
              status
              subject
              preview
            }
          }
        }
      }
    }
  }
`;

突变(CreateDraft.jsx):

// Mutation file

const draftsData = proxy.readQuery({
  query: MemberDraftsQuery,
  variables: { groupSlug },
});
console.log('draftsData', draftsData);

// NOTE: Fails here (doesn't progress to next console statement)
const messagesData = proxy.readQuery({
  query: MemberMessagesQuery,
  variables: { groupSlug },
});
console.log('messagesData', messagesData);

// Add the new draft edge to the member's drafts
draftsData.groupEdge.node.allMessages.edges.push(createdDraftEdge);

// Add the new draft edge to the member's authored messages (uses different query)
messagesData.groupEdge.node.allMessages.edges.push(createdDraftEdge);

proxy.writeQuery({
  query: MemberDraftsQuery,
  data: draftsData,
  variables: { groupSlug },
});
proxy.writeQuery({
  query: MemberMessagesQuery,
  data: messagesData,
  variables: { groupSlug },
});

相关?

StackOverflow - How to update apollo cache after mutation query with filter

这篇文章涉及与我相同的方面,但我已经处理variables中的writeQuery。但是,这是否意味着我应该try...catch进行每次writeQuery操作?如果由于其他原因失败怎么办?总而言之,不确定它是否回答了我的问题。

编辑1

经过一些更多的编码(并在下面的评论中看到),我意识到readQuery导致了问题(不是writeQuery)。由于我不喜欢使用try...catch,因为它会混淆错误而不知道导致错误的原因,因此我更新了我的方法,使try...catch只处理readQuery错误。如果在此处抛出错误,我假设查询不存在(应单独处理)或缓存数据不存在。在这两种情况下,我只是跳过写入该查询。

import { MemberDraftsQuery } from '@componens/MemberDrafts';

...
class MemberDraftDetails extends Component {
  onSubmit = (groupSlug) => {
    mutate({
      variables: {
        input: {
          content,
          subject,
          ...
        }
      },
      update: (proxy, { data: responseData }) => {
        const draftEdge = responseData.createDraft;

        // UNUSED: Could be used to validate the query actually exists (doesn't warn for some reason)
        const hasDraftsQuery = Boolean(MemberDraftsQuery);

        let hasDraftsQueryCache = true;

        // A failure to read the query means that there is no cached data (therefore cannot read/write)
        //   NOTE: Could write default data, but no reason to (since it will be fetched later)
        try {
          const draftsData = proxy.readQuery({
            query: MemberDraftsQuery,
            variables: { groupSlug },
          });
        } catch (e) {
          hasDraftsQueryCache = false;
        }

        // Only add the draft to the cache if it exists. If not, it will be queried and retrieved later
        if (hasDraftsQueryCache) {
          const newDraftEdges = data.groupEdge.node.allMessages.edges.concat(draftEdge);
          data.groupEdge.node.allMessages.edges = newDraftEdges;

          proxy.writeQuery({
            query: MemberDraftsQuery,
            data,
            variables: { groupSlug },
          });
        }
      }
    }).then().catch();
  }
}

0 个答案:

没有答案