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



我有一个带有消息列表的线程,该线程通过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 }).阿波罗文档说,应该在查询中使用@connection指令来解决这个问题。我尝试将查询更新为如下所示:

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

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

我怎么能告诉阿波罗只替换乐观响应的节点,而不是整个边缘?也许有没有另一种方法可以解决原始问题?

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

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' },
],
},
},
});
},
});
},

如果你有一双好眼睛,你会立即发现问题:插入的边缘不提供光标——这正是阿波罗客户端在警告中告诉我们的!解决方法是将光标添加到插入的边缘:

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

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

我会对此有所了解。

如果没有看到突变,我会假设它看起来像下面这样。

mutation NewMessage($message: String!, $threadId: ID!) {
sendMessage(message: $message, threadId: $threadId) {
...messageInfo
}
}

如果是这种情况,推断消息应该在连接中的位置可能是不可靠的。由于游标是不透明的字符串,因此我们无法确定此消息是否确实应该出现在最新消息之后。

相反,我会尝试如下方法。

mutation NewMessage(message: String!, threadId: ID!, $after: Cursor, first: Int) {
sendMessage(message: $message, threadId: $threadId) {
messageConnection(
after: $after,
first: $first,
before: null,
last: null
) @connection(key: "messageConnection") {
edges {
cursor
node { ...messageInfo }
}
}
}
}

此连接应包括新消息以及此后添加的任何其他消息。

以下是有关@connection指令的官方文档:https://www.apollographql.com/docs/react/advanced/caching/#the-connection-directive

最新更新