Skip to content

Commit 8bbc829

Browse files
committed
Added: tanstack-query to object list
1 parent 63784c4 commit 8bbc829

File tree

1 file changed

+52
-47
lines changed

1 file changed

+52
-47
lines changed

src/components/object-list.tsx

Lines changed: 52 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"use client";
22

3-
import { useState, useEffect } from "react";
3+
import { useState } from "react";
4+
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
45
import { toast } from "sonner";
56
import { cn } from "@/lib/utils";
67

@@ -19,10 +20,9 @@ export default function ObjectList({
1920
className = "",
2021
type = "server", // default to "server"
2122
}: {
22-
className?: "";
23+
className?: string;
2324
type?: "server" | "storage";
2425
}) {
25-
const [objects, setObjects] = useState<S3Object[]>([]);
2626
const [searchQuery, setSearchQuery] = useState("");
2727
const [selectedFolder, setSelectedFolder] = useState<string | null>(null);
2828
const [sortOrder, setSortOrder] = useState<{
@@ -34,27 +34,51 @@ export default function ObjectList({
3434
const itemsPerPage = 100;
3535
const s3Region = process.env.AWS_S3_REGION;
3636

37-
useEffect(() => {
38-
const fetchObjects = async () => {
39-
try {
40-
const res = await fetch(`/api/objects?type=${type}`);
41-
if (!res.ok) {
42-
const errorMessage = `Error: ${res.status} ${res.statusText}`;
43-
throw new Error(errorMessage);
44-
}
45-
const data = (await res.json()) as S3ObjectData;
37+
const queryClient = useQueryClient();
4638

47-
setObjects(data.objects);
48-
} catch (err) {
49-
const message = (err as Error).message;
50-
toast.error(message);
39+
// Fetch objects using TanStack Query
40+
const { data, error, isLoading } = useQuery<S3ObjectData, Error>({
41+
queryKey: ["objects", type],
42+
queryFn: async () => {
43+
const res = await fetch(`/api/objects?type=${type}`);
44+
if (!res.ok) {
45+
const errorMessage = `Error: ${res.status} ${res.statusText}`;
46+
throw new Error(errorMessage);
5147
}
52-
};
48+
return res.json() as Promise<S3ObjectData>;
49+
},
50+
});
51+
52+
const deleteMutation = useMutation({
53+
mutationFn: async (keys: string[]) => {
54+
const res = await fetch("/api/delete-objects", {
55+
method: "DELETE",
56+
headers: {
57+
"Content-Type": "application/json",
58+
},
59+
body: JSON.stringify({ keys }),
60+
});
5361

54-
fetchObjects().catch((err) => {
55-
toast.error(`Unexpected error: ${(err as Error).message}`);
56-
});
57-
}, [type]);
62+
if (!res.ok) {
63+
const errorMessage = `Error deleting objects: ${res.status} ${res.statusText}`;
64+
throw new Error(errorMessage);
65+
}
66+
67+
return keys;
68+
},
69+
onSuccess: (deletedKeys) => {
70+
queryClient.setQueryData<S3ObjectData>(["objects", type], (oldData) => ({
71+
objects: oldData?.objects.filter(
72+
(object) => !deletedKeys.includes(object.key),
73+
),
74+
}));
75+
toast.success("Selected objects deleted successfully!");
76+
setSelectedObjects([]);
77+
},
78+
onError: (error: Error) => {
79+
toast.error(error.message);
80+
},
81+
});
5882

5983
const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
6084
setSearchQuery(e.target.value);
@@ -86,39 +110,20 @@ export default function ObjectList({
86110
);
87111
};
88112

89-
const handleDeleteSelected = async () => {
113+
const handleDeleteSelected = () => {
90114
const confirmDelete = window.confirm(
91115
"Are you sure you want to delete the selected objects? This action cannot be undone.",
92116
);
93117

94-
if (!confirmDelete) {
95-
return;
118+
if (confirmDelete) {
119+
deleteMutation.mutate(selectedObjects);
96120
}
121+
};
97122

98-
try {
99-
const res = await fetch("/api/delete-objects", {
100-
method: "DELETE",
101-
headers: {
102-
"Content-Type": "application/json",
103-
},
104-
body: JSON.stringify({ keys: selectedObjects }),
105-
});
123+
if (isLoading) return <p>Loading...</p>;
124+
if (error) return <p>Error: {error.message}</p>;
106125

107-
if (!res.ok) {
108-
const errorMessage = `Error deleting objects: ${res.status} ${res.statusText}`;
109-
throw new Error(errorMessage);
110-
}
111-
112-
toast.success("Selected objects deleted successfully!");
113-
setObjects((prevObjects) =>
114-
prevObjects.filter((object) => !selectedObjects.includes(object.key)),
115-
);
116-
setSelectedObjects([]);
117-
} catch (err) {
118-
const message = (err as Error).message;
119-
toast.error(message);
120-
}
121-
};
126+
const objects = data?.objects ?? [];
122127

123128
const filteredObjects = objects.filter((object) => {
124129
const matchesFolder = selectedFolder

0 commit comments

Comments
 (0)