Skip to content

Commit 483d5ae

Browse files
committed
feat: implement optimistic updates for article deletion and restoration in ArticleList component
1 parent 3522114 commit 483d5ae

File tree

1 file changed

+60
-8
lines changed

1 file changed

+60
-8
lines changed

src/app/dashboard/_components/ArticleList.tsx

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ import {
2525
useMutation,
2626
useQueryClient,
2727
} from "@tanstack/react-query";
28-
import { differenceInHours } from "date-fns";
28+
import clsx from "clsx";
29+
import { addDays, differenceInHours } from "date-fns";
2930
import { TrashIcon } from "lucide-react";
3031
import Link from "next/link";
3132

@@ -50,9 +51,33 @@ const ArticleList = () => {
5051
actionPromisify(articleActions.scheduleArticleDelete(article_id), {
5152
enableToast: true,
5253
}),
53-
onSuccess() {
54-
// TODO: optimistic update
55-
feedInfiniteQuery.refetch();
54+
onMutate: async (article_id: string) => {
55+
await queryClient.cancelQueries({ queryKey: ["dashboard-articles"] });
56+
57+
const previousData = queryClient.getQueryData(["dashboard-articles"]);
58+
59+
queryClient.setQueryData(["dashboard-articles"], (old: any) => {
60+
if (!old) return old;
61+
62+
return {
63+
...old,
64+
pages: old.pages.map((page: any) => ({
65+
...page,
66+
nodes: page.nodes.map((article: any) =>
67+
article.id === article_id
68+
? { ...article, delete_scheduled_at: addDays(new Date(), 7) }
69+
: article
70+
),
71+
})),
72+
};
73+
});
74+
75+
return { previousData };
76+
},
77+
onError: (err, variables, context) => {
78+
if (context?.previousData) {
79+
queryClient.setQueryData(["dashboard-articles"], context.previousData);
80+
}
5681
},
5782
});
5883

@@ -62,9 +87,33 @@ const ArticleList = () => {
6287
articleActions.restoreShceduleDeletedArticle(article_id),
6388
{ enableToast: true }
6489
),
65-
onSuccess() {
66-
// TODO: optimistic update
67-
feedInfiniteQuery.refetch();
90+
onMutate: async (article_id: string) => {
91+
await queryClient.cancelQueries({ queryKey: ["dashboard-articles"] });
92+
93+
const previousData = queryClient.getQueryData(["dashboard-articles"]);
94+
95+
queryClient.setQueryData(["dashboard-articles"], (old: any) => {
96+
if (!old) return old;
97+
98+
return {
99+
...old,
100+
pages: old.pages.map((page: any) => ({
101+
...page,
102+
nodes: page.nodes.map((article: any) =>
103+
article.id === article_id
104+
? { ...article, delete_scheduled_at: null }
105+
: article
106+
),
107+
})),
108+
};
109+
});
110+
111+
return { previousData };
112+
},
113+
onError: (err, variables, context) => {
114+
if (context?.previousData) {
115+
queryClient.setQueryData(["dashboard-articles"], context.previousData);
116+
}
68117
},
69118
});
70119

@@ -91,7 +140,10 @@ const ArticleList = () => {
91140
return page?.nodes.map((article) => (
92141
<article
93142
key={article.id}
94-
className="flex justify-between flex-col md:flex-row py-3 space-y-2"
143+
className={clsx(
144+
"flex justify-between flex-col md:flex-row py-3 space-y-2 px-2",
145+
{ "bg-destructive/10": !!article.delete_scheduled_at }
146+
)}
95147
>
96148
<div className="flex flex-col">
97149
<p>{article.handle}</p>

0 commit comments

Comments
 (0)