使用带有订阅的乐观 UI 有意义吗?
所以基本上:
addChannelMutation({
variables: { name: eventValue },
optimisticResponse: {
__typename: "Mutation",
addChannel: {
__typename: "Channel",
id: data.channels.length,
name: eventValue
}
},
update: (store, { data: { addChannel } }) => {
// Read the data from our cache for this query.
const data = store.readQuery({ query: channelsListQuery });
// Add our comment from the mutation to the end.
data.channels.push(addChannel);
// Write our data back to the cache.
store.writeQuery({ query: channelsListQuery, data });
}
}).then(res => {});
它添加两次相同的项目,触发重复键异常。 那么乐观的 UI 对订阅有意义吗?
optimisticResponse
服务器收到响应之前触发update
。然后,当服务器响应时,将再次触发update
,并将乐观占位符替换为响应。
订阅仅在服务器突变解析后发出,因此基本上是在服务器响应时发出的。
如果未包含乐观 UI,并且存在任何类型的延迟,则在服务器发送响应之前不会显示结果。这可能是一个问题,例如在聊天应用中,如果用户在单击发送按钮后没有看到他们的消息。他们会继续点击按钮并多次发送消息:/
为了在使用优化 UI 和订阅时打击欺骗,有两种策略包括:
检查客户端上的重复:
在
update
和updateQuery
函数中:// super simplified dupe doc checker function isDuplicateDocument(newDocument, existingDocuments) { return newDocument.id !== null && existingDocuments.some(doc => newDocument.id === doc.id); } addChannelMutation({ variables: { name: eventValue }, optimisticResponse: { __typename: "Mutation", addChannel: { __typename: "Channel", id: data.channels.length, name: eventValue } }, update: (store, { data: { addChannel } }) => { // Read the data from our cache for this query. const data = store.readQuery({ query: channelsListQuery }); if (isDuplicateDocument(addChannel, data.channels) { return; } // Add our comment from the mutation to the end. data.channels.push(addChannel); // Write our data back to the cache. store.writeQuery({ query: channelsListQuery, data }); } }).then(res => {});
以及订阅中的
updateQuery
内部:subscribeToMore({ ... updateQuery: (previousResult, { subscriptionData }) => { const newChannel = subscriptionData.data.addChannel; // if it's our own mutation // we might get the subscription result // after the mutation result. if (isDuplicateDocument( newChannel, previousResult.channels) ) { return previousResult; } return update(previousResult, { channels: { $push: [newChannel], }, }); },
或者,您可以将服务器上的订阅限制为不向新频道的创建者发出。