Apollo JS Подписки Оптимистичный пользовательский интерфейс
Имеет ли смысл иметь Optimistic 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 => {});
Он добавляет дважды один и тот же элемент, вызывая исключение дубликата ключа. Таким образом, оптимистичный интерфейс имеет смысл с подписками?
1 ответ
optimisticResponse
триггеры update
до получения ответа сервером. Затем, когда сервер отвечает, update
запускается снова и заменяет оптимистический заполнитель ответом.
Подписки будут генерироваться только после разрешения мутации сервера, в основном, когда сервер отвечает.
Если вы не включили Optimistic UI и у вас были какие-либо задержки, результат не будет отображаться, пока сервер не отправит ответ. Это может быть проблемой, например, в приложении чата, если пользователь не видит свое сообщение, как только он нажимает кнопку отправки. Они будут продолжать нажимать кнопку и отправлять сообщение несколько раз:/
Для борьбы с обманщиками при использовании Optimisic 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], }, }); },
Или вы можете ограничить подписку на сервере, чтобы не отправлять ее создателю нового канала.