[Chat] Fix optimistic updates by using partial keys (#10838)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Samuel Newman
2026-06-10 13:56:54 +03:00
committed by GitHub
parent 9a2e636c17
commit 7379ad3c3b
3 changed files with 191 additions and 143 deletions
+32 -37
View File
@@ -1,4 +1,3 @@
import {type ChatBskyConvoListConvos} from '@atproto/api'
import {useMutation, useQueryClient} from '@tanstack/react-query'
import {DM_SERVICE_HEADERS} from '#/lib/constants'
@@ -9,7 +8,11 @@ import {
markAllRead as markAllRequestsRead,
RQKEY_ROOT as REQUESTS_RQKEY_ROOT,
} from './list-conversation-requests'
import {RQKEY as CONVO_LIST_KEY} from './list-conversations'
import {
type ConvoListQueryData,
RQKEY_PARTIAL as CONVO_LIST_PARTIAL_KEY,
RQKEY_ROOT as CONVO_LIST_ROOT_KEY,
} from './list-conversations'
export function useUpdateAllRead(
status: 'accepted' | 'request',
@@ -36,18 +39,19 @@ export function useUpdateAllRead(
return data
},
onMutate: () => {
let prevPages: ChatBskyConvoListConvos.OutputSchema[] = []
// snapshot every convo-list cache up front so onError can restore them
// all by their exact keys
const prevConvoListQueries =
queryClient.getQueriesData<ConvoListQueryData>({
queryKey: [CONVO_LIST_ROOT_KEY],
})
let prevRequestsQueries: Array<
[readonly unknown[], ConvoRequestListQueryData | undefined]
> = []
queryClient.setQueryData(
CONVO_LIST_KEY(status),
(old?: {
pageParams: Array<string | undefined>
pages: Array<ChatBskyConvoListConvos.OutputSchema>
}) => {
queryClient.setQueriesData(
{queryKey: CONVO_LIST_PARTIAL_KEY(status)},
(old?: ConvoListQueryData) => {
if (!old) return old
prevPages = old.pages
return {
...old,
pages: old.pages.map(page => {
@@ -64,13 +68,10 @@ export function useUpdateAllRead(
}
},
)
// remove unread convos from the badge query
queryClient.setQueryData(
CONVO_LIST_KEY('all', 'unread'),
(old?: {
pageParams: Array<string | undefined>
pages: Array<ChatBskyConvoListConvos.OutputSchema>
}) => {
// remove unread convos from the badge queries
queryClient.setQueriesData(
{queryKey: CONVO_LIST_PARTIAL_KEY('all', 'unread')},
(old?: ConvoListQueryData) => {
if (!old) return old
return {
...old,
@@ -94,10 +95,15 @@ export function useUpdateAllRead(
)
}
onMutate?.()
return {prevPages, prevRequestsQueries}
return {prevConvoListQueries, prevRequestsQueries}
},
onSuccess: () => {
void queryClient.invalidateQueries({queryKey: CONVO_LIST_KEY(status)})
void queryClient.invalidateQueries({
queryKey: CONVO_LIST_PARTIAL_KEY(status),
})
void queryClient.invalidateQueries({
queryKey: CONVO_LIST_PARTIAL_KEY('all', 'unread'),
})
if (status === 'request') {
void queryClient.invalidateQueries({queryKey: [REQUESTS_RQKEY_ROOT]})
}
@@ -105,28 +111,17 @@ export function useUpdateAllRead(
},
onError: (error, _, context) => {
logger.error(error)
queryClient.setQueryData(
CONVO_LIST_KEY(status),
(old?: {
pageParams: Array<string | undefined>
pages: Array<ChatBskyConvoListConvos.OutputSchema>
}) => {
if (!old) return old
return {
...old,
pages: context?.prevPages || old.pages,
}
},
)
if (status === 'request' && context?.prevRequestsQueries) {
if (context?.prevConvoListQueries) {
for (const [queryKey, prevData] of context.prevConvoListQueries) {
queryClient.setQueryData(queryKey, prevData)
}
}
if (context?.prevRequestsQueries) {
for (const [queryKey, prevData] of context.prevRequestsQueries) {
queryClient.setQueryData(queryKey, prevData)
}
}
void queryClient.invalidateQueries({queryKey: CONVO_LIST_KEY(status)})
void queryClient.invalidateQueries({
queryKey: CONVO_LIST_KEY('all', 'unread'),
})
void queryClient.invalidateQueries({queryKey: [CONVO_LIST_ROOT_KEY]})
if (status === 'request') {
void queryClient.invalidateQueries({queryKey: [REQUESTS_RQKEY_ROOT]})
}