mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-10 23:36:14 -05:00
Invalidated queries when liking and unliking objects
This gives us some live-ness in the frontend, so that when you unlike an item in the liked view - it will be removed from the list, and the count will be updated.
This commit is contained in:
parent
bd66efa70a
commit
2749296fea
2 changed files with 79 additions and 3 deletions
|
@ -146,10 +146,11 @@ const FeedItemStats: React.FC<{
|
||||||
} else {
|
} else {
|
||||||
unlikeMutation.mutate(object.id);
|
unlikeMutation.mutate(object.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
setIsLiked(!isLiked);
|
setIsLiked(!isLiked);
|
||||||
|
|
||||||
setIsClicked(false); // Reset the animation class after request completed
|
setIsClicked(false); // Reset the animation class after request completed
|
||||||
|
|
||||||
// Call the requested `onLikeClick`
|
// Call the requested `onLikeClick`
|
||||||
onLikeClick();
|
onLikeClick();
|
||||||
setTimeout(() => setIsClicked(false), 300);
|
setTimeout(() => setIsClicked(false), 300);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import {ActivityPubAPI} from '../api/activitypub';
|
import {ActivityPubAPI} from '../api/activitypub';
|
||||||
import {useBrowseSite} from '@tryghost/admin-x-framework/api/site';
|
import {useBrowseSite} from '@tryghost/admin-x-framework/api/site';
|
||||||
import {useMutation, useQuery} from '@tanstack/react-query';
|
import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query';
|
||||||
|
|
||||||
const useSiteUrl = () => {
|
const useSiteUrl = () => {
|
||||||
const site = useBrowseSite();
|
const site = useBrowseSite();
|
||||||
|
@ -27,21 +27,96 @@ export function useLikedForUser(handle: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useLikeMutationForUser(handle: string) {
|
export function useLikeMutationForUser(handle: string) {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
const siteUrl = useSiteUrl();
|
const siteUrl = useSiteUrl();
|
||||||
const api = createActivityPubAPI(handle, siteUrl);
|
const api = createActivityPubAPI(handle, siteUrl);
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn(id: string) {
|
mutationFn(id: string) {
|
||||||
return api.like(id);
|
return api.like(id);
|
||||||
|
},
|
||||||
|
onMutate: (id) => {
|
||||||
|
const previousInbox = queryClient.getQueryData([`inbox:${handle}`]);
|
||||||
|
if (previousInbox) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
queryClient.setQueryData([`inbox:${handle}`], (old?: any[]) => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
return old?.map((item: any) => {
|
||||||
|
if (item.object.id === id) {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
object: {
|
||||||
|
...item.object,
|
||||||
|
liked: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// This sets the context for the onError handler
|
||||||
|
return {previousInbox};
|
||||||
|
},
|
||||||
|
onError: (_err, _id, context) => {
|
||||||
|
if (context?.previousInbox) {
|
||||||
|
queryClient.setQueryData([`inbox:${handle}`], context?.previousInbox);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onSettled: () => {
|
||||||
|
queryClient.invalidateQueries({queryKey: [`liked:${handle}`]});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useUnlikeMutationForUser(handle: string) {
|
export function useUnlikeMutationForUser(handle: string) {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
const siteUrl = useSiteUrl();
|
const siteUrl = useSiteUrl();
|
||||||
const api = createActivityPubAPI(handle, siteUrl);
|
const api = createActivityPubAPI(handle, siteUrl);
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn(id: string) {
|
mutationFn: (id: string) => {
|
||||||
return api.unlike(id);
|
return api.unlike(id);
|
||||||
|
},
|
||||||
|
onMutate: async (id) => {
|
||||||
|
const previousInbox = queryClient.getQueryData([`inbox:${handle}`]);
|
||||||
|
const previousLiked = queryClient.getQueryData([`liked:${handle}`]);
|
||||||
|
|
||||||
|
if (previousInbox) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
queryClient.setQueryData([`inbox:${handle}`], (old?: any[]) => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
return old?.map((item: any) => {
|
||||||
|
if (item.object.id === id) {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
object: {
|
||||||
|
...item.object,
|
||||||
|
liked: false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (previousLiked) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
queryClient.setQueryData([`liked:${handle}`], (old?: any[]) => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
return old?.filter((item: any) => item.object.id !== id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// This sets the context for the onError handler
|
||||||
|
return {previousInbox, previousLiked};
|
||||||
|
},
|
||||||
|
onError: (_err, _id, context) => {
|
||||||
|
if (context?.previousInbox) {
|
||||||
|
queryClient.setQueryData([`inbox:${handle}`], context?.previousInbox);
|
||||||
|
}
|
||||||
|
if (context?.previousLiked) {
|
||||||
|
queryClient.setQueryData([`liked:${handle}`], context?.previousLiked);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue