desktop: cancel in-flight channel fetch before optimistic reaction write

The reaction onMutate snapshotted the cache and wrote the optimistic
kind:7 synchronously, but did not cancel an in-flight useChannelMessages
fetch first. That queryFn ends with setQueryData(queryKey, mergedHistory)
built from a pre-click snapshot, so a fetch resolving just after the
click would clobber the optimistic reaction until the next backfill —
the same race the sibling send-message onMutate already guards against.

Make onMutate async and await queryClient.cancelQueries({ queryKey })
before snapshotting, matching the send-message mutation. Narrow but real;
no behavior change when no fetch is in flight (cancelQueries is a no-op).

Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
This commit is contained in:
npub1qyvc0c5kl4gqv2fd97fsk46tu378sqgy35vc83rvgfwne90sel7s0ed67d
2026-06-21 09:58:24 -04:00
parent 87e7f3578c
commit 1e6e0eefb8

View File

@@ -519,13 +519,17 @@ export function useToggleReactionMutation() {
// channel cache ourselves, optimistically, or the reactor's own reaction
// stays invisible until the next channel switch. Mirrors the apply-on-
// success cache writes in the edit/delete mutations below.
onMutate: ({ eventId, emoji, remove, channelId }) => {
onMutate: async ({ eventId, emoji, remove, channelId }) => {
const pubkey = identityQuery.data?.pubkey;
if (!channelId || !pubkey) {
return undefined;
}
const queryKey = channelMessagesKey(channelId);
// Cancel any in-flight channel fetch so its post-write setQueryData
// can't clobber the optimistic reaction with a pre-write snapshot
// (matches the send-message onMutate below).
await queryClient.cancelQueries({ queryKey });
const previous = queryClient.getQueryData<RelayEvent[]>(queryKey) ?? [];
const pubkeyLower = pubkey.toLowerCase();
const trimmedEmoji = emoji.trim();