javascript - 如何在突变后更新分页列表?

标签 javascript graphql apollo react-apollo apollo-client

我有一个包含消息列表的线程,它是通过 GET_THREAD_MESSAGES 查询获取的。该查询是分页的,根据用户之前是否看过该线程,可能会加载第一页、最后一页或仅加载新消息。 (即任何 first/after/before/last 都可以传递任何值)

thread(id: "asdf") {
  messageConnection(after: $after, first: $first, before: $before, last: $last) {
    edges {
      cursor
      node { ...messageInfo }
    }
  }
}

现在我有一个 sendMessage 突变,我调用它然后在该突变的 update 方法中我想乐观地将发送的消息添加到线程消息中更好的用户体验。如果没有分页,我知道我会这样做:

const data = store.readQuery({
  query: GET_THREAD_MESSAGES,
  variables: { id: message.threadId }
})

data.messageConnection.edges.push(newMessageEdge);

store.writeQuery({
  query: GET_THREAD_MESSAGES,
  variables: { id: message.threadId },
  data,
})

不幸的是,因为我知道有分页,所以 store.readQuery 调用会抛出一个错误,提示“找不到该线程的字段 messageConnection”,因为该字段是现在类似于 messageConnection({ after: 'jfds1223asdhfl', first: 50, before: null, last: null })Apollo docs说应该在查询中使用 @connection 指令来解决这个问题。我尝试将查询更新为如下所示:

thread(id: "asdf") {
  messageConnection(...) @connection(key: "messageConnection") {
    edges {
      cursor
      node { ...messageInfo }
    }
  }
}

不幸的是,当我使用乐观更新返回并正确显示时,但一旦服务器返回存储的实际消息,我就会收到一条错误消息,提示 “{ node: { id: 中缺少字段游标: '...', timestamp: '...'",因为显然服务器返回的消息不是 MessageConnectionEdge,它只是节点,因此没有光标字段。

如何告诉 Apollo 只替换乐观响应的节点,而不是整个边缘?是否有另一种方法可以解决原始问题?

最佳答案

呼,我终于解决了这个问题。结果证明问题根本不在突变中,而是在为线程中的新消息并行运行的订阅中。 (捂脸)

TL;DR:如果您在突变发生变化时订阅了相同的数据,请确保在两种更新方法中包含相同的字段!

订阅方法如下所示:

subscribeToNewMessages: () => {
  return props.data.subscribeToMore({
    document: subscribeToNewMessages,
    variables: {
      thread: props.ownProps.id,
    },
    updateQuery: (prev, { subscriptionData }) => {
      const newMessage = subscriptionData.data.messageAdded;
      return Object.assign({}, prev, {
        ...prev,
        thread: {
          ...prev.thread,
          messageConnection: {
            ...prev.thread.messageConnection,
            edges: [
              ...prev.thread.messageConnection.edges,
              { node: newMessage, __typename: 'ThreadMessageEdge' },
            ],
          },
        },
      });
    },
  });
},

如果你有好眼力,你会立即发现问题:插入的边缘不提供光标——这正是 Apollo Client 在警告中告诉我们的!解决方法是将光标添加到插入的边缘:

{ node: newMessage, cursor: newMessage.id, __typename: 'ThreadMessageEdge' }

希望这可以帮助遇到此警告的其他人,确保对订阅和突变 update 方法进行三重检查!

关于javascript - 如何在突变后更新分页列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48242062/

相关文章:

javascript - 在 React JS 中使用 Router 时如何使用 Context API 传递状态

docker - Prisma部署Docker错误 “Could not connect to server”

graphql - GraphQL 中的查看器字段是什么意思?

graphql - 如何替换 Fauna 中多对多关系中的所有连接

node.js - id 不能在 graphQL where 子句中使用?

node.js - 如何将特殊字符放入 apollo graphQL 服务器的枚举值中?

javascript - 如何删除以下 promise 捕获而不使代码挂起?

javascript - $ 未定义,但 jQuery 在 WordPress 中已定义

javascript - 相同的动画在不同的方向上花费的时间更长

reactjs - Apollo客户端查询错误: "Network error: Failed to fetch" How to troubleshoot?