Skip to content

Instantly share code, notes, and snippets.

@wobsoriano
Last active July 14, 2021 06:46
Show Gist options
  • Save wobsoriano/d61715694d89fc5c8df895b9306ce687 to your computer and use it in GitHub Desktop.
Save wobsoriano/d61715694d89fc5c8df895b9306ce687 to your computer and use it in GitHub Desktop.
React Query useMutation and TypeScript
import { InfiniteData, useMutation, useQueryClient } from 'react-query';
import { ExtendPayload } from '../globals';
import { useAuthStore } from '../store';
import { MessageListItem, MessageListResponse } from './useMessageList';
import { httpClient, stringifyQuery } from './utils';
interface CreateMessageBody {
to: string;
message: string;
}
export const useCreateMessage = () => {
const user = useAuthStore((state) => state.user);
const queryClient = useQueryClient();
return useMutation(
async (body: CreateMessageBody) => {
const { data } = await httpClient.post<ExtendPayload<MessageListItem>>(
`/message_add`,
stringifyQuery({
from: user?.guid,
to: body.to,
message: body.message,
})
);
return data;
},
{
onMutate: async (variables) => {
const queryKey = ['messages', { from: user?.guid, to: variables.to }];
// Cancel any outgoing refetches (so they don't overwrite our optimistic update)
await queryClient.cancelQueries(queryKey);
// Snapshot the previous value
const previousData = queryClient.getQueryData<InfiniteData<MessageListResponse>>(queryKey);
// Optimistically update to the new value
if (previousData) {
const newPagesArray = previousData?.pages.map((page, index) => {
// Add to first page
if (index === 0) {
const newMessage = {...};
const list = page.payload ? [...page.payload.list, newMessage] : [newMessage];
return {
...page,
payload: {
...page.payload,
list,
},
};
}
return page;
});
queryClient.setQueryData(queryKey, {
...previousData,
pages: newPagesArray,
});
}
return {
previousData,
};
},
// If the mutation fails, use the context returned from onMutate to roll back
onError: (_error, variables, context: any) => {
if (context?.previousData) {
queryClient.setQueryData<InfiniteData<MessageListResponse>>(
['messages', { from: user?.guid, to: variables.to }],
context.previousData
);
}
},
// Always refetch after error or success:
onSettled: (_data, _error, variables, _context) => {
queryClient.invalidateQueries([
'messages',
{ from: user?.guid, to: variables.to },
]);
},
}
);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment