Tutorial React TanStack Query #8: Delete Data (useMutation & invalidateQueries)


👍 1 ❤️ 1 💡 0 🔥 0 🙌 0 🥳 1
Tutorial React TanStack Query #8: Delete Data (useMutation & invalidateQueries)

Halo teman-teman semuanya, setelah sebelumnya kita belajar bagaimana melakukan edit dan update data ke API menggunakan kombinasi useQuery dan useMutation, di tutorial kali ini kita akan lanjut belajar bagaimana cara melakukan hapus data atau delete ke API menggunakan TanStack Query. Teknik yang akan kita gunakan kali ini yaitu:

  • useMutation untuk menjalankan proses hapus data.
  • queryClient.invalidateQueries() untuk me-refresh data setelah berhasil dihapus.

Langkah 1 - Delete Data Dengan useMutation dan invalidateQueries

Langsung saja, silahkan teman-teman buka file src/views/products/index.jsx, kemudian ubah semua kode-nya menjadi seperti berikut ini.

src/views/products/index.jsx

//import hook useQuery dan useMutation
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';

//import Link
import { Link } from 'react-router';

//import service Api
import Api from '../../api';

const ProductIndex = () => {

    // Initialize QueryClient
    const queryClient = useQueryClient();

    // Fetch data from API using react-query
    const { data, isLoading, isError, error } = useQuery({

        // Set the query key
        queryKey: ['products'],

        // Set the query function
        queryFn: async () => {
            const res = await Api.get('/api/products');
            return res.data.data.data;
        }
    });

    // Mutation for deleting product
    const deleteProduct = useMutation({
        mutationFn: async (id) => {
            await Api.delete(`/api/products/${id}`);
        },
        onSuccess: () => {
            // Refresh the product list after deletion
            queryClient.invalidateQueries({ queryKey: ['products'] });
        },
    });

    // Handle Delete Button Click
    const handleDelete = (id) => {
        if (confirm("Are you sure you want to delete this product?")) {

            // Call the delete mutation
            deleteProduct.mutate(id);
        }
    };

    return (
        <div className="container mt-5 mb-5">
            <div className="row">
                <div className="col-md-12">
                    <Link
                        to="/products/create"
                        className="btn btn-md btn-success rounded-5 shadow border-0 mb-3"
                    >
                        ADD NEW PRODUCT
                    </Link>
                    <div className="card border-0 rounded-3 shadow">
                        <div className="card-body">

                            {/* Loading State */}
                            {isLoading && (
                                <div className="alert alert-info text-center">Loading...</div>
                            )}

                            {/* Error State */}
                            {isError && (
                                <div className="alert alert-danger text-center">
                                    Error: {error.message}
                                </div>
                            )}

                            {/* Tabel Produk */}
                            {!isLoading && !isError && (
                                <table className="table table-bordered">
                                    <thead className="bg-dark text-white">
                                        <tr>
                                            <th scope="col">Image</th>
                                            <th scope="col">Title</th>
                                            <th scope="col">Description</th>
                                            <th scope="col">Price</th>
                                            <th scope="col">Stock</th>
                                            <th scope="col" style={{ width: "15%" }}>Actions</th>
                                        </tr>
                                    </thead>
                                    <tbody>
                                        {data.length > 0 ? (
                                            data.map((product) => (
                                                <tr key={product.id}>
                                                    <td className="text-center">
                                                        <img
                                                            src={product.image}
                                                            alt={product.title}
                                                            width="200"
                                                            className="rounded-3"
                                                        />
                                                    </td>
                                                    <td>{product.title}</td>
                                                    <td>{product.description}</td>
                                                    <td>{product.price?.toLocaleString("id-ID")}</td>
                                                    <td>{product.stock}</td>
                                                    <td className="text-center">
                                                        <Link
                                                            to={`/products/edit/${product.id}`}
                                                            className="btn btn-sm btn-primary rounded-5 shadow border-0 me-2"
                                                        >
                                                            EDIT
                                                        </Link>
                                                        <button
                                                            onClick={() => handleDelete(product.id)}
                                                            className="btn btn-sm btn-danger rounded-5 shadow border-0"
                                                            disabled={deleteProduct.isPending}
                                                        >
                                                            {deleteProduct.isPending ? "..." : "DELETE"}
                                                        </button>
                                                    </td>
                                                </tr>
                                            ))
                                        ) : (
                                            <tr>
                                                <td colSpan={6} className="text-center">
                                                    <div className="alert alert-danger mb-0">
                                                        No data available
                                                    </div>
                                                </td>
                                            </tr>
                                        )}
                                    </tbody>
                                </table>
                            )}
                        </div>
                    </div>
                </div>
            </div>
        </div>
    );
};

export default ProductIndex;

Dari perubahan kode di atas, pertama kita import useQueryClient dari TanStack Query.

//import hook useQuery dan useMutation
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';

Kemudian kita lakukan inisialisasi queryClient.

// Initialize QueryClient
const queryClient = useQueryClient();

Selanjutnya, kita membuat mutation dengan nama deleteProduct.

// Mutation for deleting product
const deleteProduct = useMutation({

	//...
	
});

Di dalamnya, untuk mutationFn kita memanggil REST API untuk proses delete data, yaitu endpoint /api/products/:id dan method yang digunakan adalah DELETE.

mutationFn: async (id) => {

	await Api.delete(`/api/products/${id}`);
	
},

Jika berhasil, maka kita akan lakukan invalidateQuery ke sebuah queryKey yang bernama products. Sehingga list data products-nya akan diperbarui.

onSuccess: () => {

  // Refresh the product list after deletion
  queryClient.invalidateQueries({ queryKey: ['products'] });

},

Selanjutnya, kita membuat function yang bernama handleDelete. Fungsi ini akan dijalankan ketika button DELETE diklik.

<button
    onClick={() => handleDelete(product.id)}
    className="btn btn-sm btn-danger rounded-5 shadow border-0"
    disabled={deleteProduct.isPending}
>

    {deleteProduct.isPending ? "..." : "DELETE"}

</button>
const handleDelete = (id) => {

	//...
	
}

Di dalamnya, kita membuat sebuah konfirmasi, jika bernailai true, maka kita akanmemanggil mutation yang bernama deleteProduct dan mengirimkan id.

// Call the delete mutation
deleteProduct.mutate(id);

Langkah 2 - Uji Coba Delete Data

Sekarang silahkan teman-teman coba klik button DELETE di salah satu data yang dimiliki, jika berhasil maka kurang lebih seperti berikut ini.

Silahkan klik OK, maka data product berhasil dihapus.

Kesimpulan

Pada tutorial ini, kita telah belajar cara menghapus data ke API menggunakan useMutation dan melakukan invalidasi query menggunakan queryClient.invalidateQueries() agar data otomatis di-refresh.

Jika teman-teman ada kendala saat belajar, jangan sungkan-sungkan untuk bertanya melalui kolom komentar atau group Telegram milik SantriKoding.

Terima Kasih


Fika Ridaul Maulayya
Full-Stack Developer, Content Creator and CO-Founder SantriKoding.com

Suka dengan tulisan di SantriKoding? Kamu bisa memberikan dukungan dengan berdonasi atau bagikan konten ini di sosial media. Terima kasih atas dukungan Anda!

KEBIJAKAN KOMENTAR

Saat memberikan komenatar silahkan memberikan informasi lengkap tentang error, seperti: screenshot, link kode, dll. Baca aturan komentar kami