Supabase와 CRUD 개발을 했다면 기능을 구현해주자.
components/searchComponent.tsx
"use client";
import { Input } from "@material-tailwind/react";
export default function SearchComponent({ searchInput, setSearchInput }){
return (
<Input
value={searchInput}
onChange={(e) => setSearchInput(e.target.value)}
label="Search Image"
icon={<i className="fa-solid fa-magnifying-glass" />}
/>
)
}
components/file-dragdropzone.tsx
"use client";
import { Spinner } from "@material-tailwind/react";
import { useMutation } from "@tanstack/react-query";
import { uploadFile } from "actions/storageActions";
import { queryClient } from "config/ReactClientProivider";
import { useCallback } from "react";
import { useDropzone } from "react-dropzone";
export default function FileDragDropZone(){
const uploadImageMutation = useMutation({
mutationFn: uploadFile,
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: ["images"],
})
}
});
const onDrop = useCallback( async (acceptedFiles) => {
if(acceptedFiles.length > 0){
const formData = new FormData();
acceptedFiles.forEach((file) => {
formData.append(file.name, file);
});
const result = await uploadImageMutation.mutate(formData);
}
}, []);
const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop });
return (
<div
{...getRootProps()}
className="w-full py-20 border-4 border-dotted border-indigo-700 flex flex-col items-center justify-center cursor-pointer">
<input {...getInputProps()} />
{uploadImageMutation.isPending ? (<Spinner />) :
( isDragActive ? (
<p>파일을 놓아주세요.</p>
) : (
<p>파일을 여기에 끌어다 놓거나 클릭하여 업로드하세요.</p>
)
)}
</div>
)
}
components/dropbox-image-list.tsx
"use client";
import { useQuery } from "@tanstack/react-query";
import DropboxImage from "./dropbox-image";
import { searchFiles } from "actions/storageActions";
import { Spinner } from "@material-tailwind/react";
export default function DropboxImageList({ searchInput }) {
const searchImageQuery = useQuery({
queryKey: ["images", searchInput],
queryFn: () => searchFiles(searchInput),
})
return (
<section className="grid md:grid-cols-3 lg:grid-cols-4 grid-cols-2">
{searchImageQuery.isLoading && <Spinner />}
{searchImageQuery.data &&
searchImageQuery.data.map(image =>(
<DropboxImage key={image.id} image={image} />
))}
</section>
)
}
import { IconButton, Spinner } from "@material-tailwind/react";
import { useMutation } from "@tanstack/react-query";
import { deleteFile } from "actions/storageActions";
import { queryClient } from "config/ReactClientProivider";
import { getImageUrl } from "utils/supabase/storage";
export default function DropboxImage({ image }){
const deleteFileMutation = useMutation({
mutationFn: deleteFile,
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: ["images"],
})
}
})
return (
<div className="relative w-full flex flex-col gap-2 p-4 border borer-gray-100 rounded-2xl shadow-md">
{/* Image */}
<div>
<img src={getImageUrl(image.name)} className="w-full aspect-square rounded-2xl" />
</div>
{/* File Name */}
<div className="font-bold">{image.name}</div>
{/* Delete Button */}
<div className="absolute top-2 right-4">
<IconButton color="red" onClick={() => {deleteFileMutation.mutate(image.name);}}>
{deleteFileMutation.isPending ? ( <Spinner /> ) : (
<i className="fas fa-trash" />
)}
</IconButton>
</div>
</div>
)
}
이렇게 해서 간단하게 File Upload 할 수 있는 Minibox를 만들어 보았다.
간단하지만 CRUD 나 React-Query에 활용까지 공부할 수 있었고,
File을 FormData에 저장해서 한번에 한개씩 올리는 것과 여러개를 올리는 방식에 대해서도 배울 수 있었다.
간단한 기초지만 이것부터 하나하나 배우면서 활용할 수 있도록 내꺼로 만들어야겠다.
완성
