Tutorial React TanStack Query #5: Fetch Data dari API (useQuery)


👍 1 ❤️ 1 💡 1 🔥 2 🙌 1 🥳 1
Tutorial React TanStack Query #5: Fetch Data dari API (useQuery)

Halo teman-teman semuanya, pada artikel sebelumnya kita semua telah belajar menginstall dan konfigurasi TanStack Query di React dan sekarang saatnya kita belajar bagaimana cara mengambil data (fetching) dari API menggunakan hook useQuery.

Apa itu useQuery?

useQuery adalah hook yang disediakan oleh TanStack Query untuk mengambil (fetch) data secara otomatis dari API. Hook ini sangat powerful karena sudah mendukung banyak fitur seperti:

  • Caching otomatis,
  • Refetch otomatis,
  • Loading dan error state,
  • Dan masih banyak lagi.

Langkah 1 - Installasi Axios

Langkah pertama yang harus kita lakukan adalah menginstall library tambahan yang bernama Axios. Library ini digunakan untuk melakukan Http request ke server dengan lebih mudah dan cepat.

Silahkan teman-teman jalankan perintah berikut ini di dalam terminal/CMD dan pastikan sudah berada di dalam project React-nya.

npm install axios@1.8.4

Silahkan tunggu proses installasinya sampai selesai dan pastikan teman-teman terhubung dengan internet.

Langkah 2 - Konfigurasi Endpoint API

Setelah menginstal Axios, langkah selanjutnya adalah membuat instance Axios agar lebih mudah mengelola perubahan domain API. Dengan ini, kita hanya perlu mengubah satu baris kode saat ada perubahan, tanpa harus mengganti alamat API di banyak tempat.

Silahkan teman-teman buat folder dengan nama api di dalam folder src, kemudian tambahkan file index.js dan masukkan kode berikut ini di dalamnya.

src/api/index.js

//import axios
import axios from 'axios';

const Api = axios.create({
    //set default endpoint API
    baseURL: 'http://localhost:8000'
})

export default Api

Coba teman-teman perhatikan dari penambahan kode di atas, pada bagian baseURL itu merupakan alamat domain dari project Laravel.

Langkah 3 - Fetch Data Dengan useQuery

Silahkan teman-teman buat folder baru dengan nama products di dalam folder src/views, kemudian di dalam folder products silahkan buat file baru dengan nama index.jsx dan masukkan kode berikut ini di dalamnya.

src/views/products/index.jsx

//import hook useQuery
import { useQuery } from '@tanstack/react-query';

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

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

const ProductIndex = () => {

    // 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;
        }
    });

    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 className="btn btn-sm btn-danger rounded-5 shadow border-0">
                                                            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 penambahan kode di atas, pertama kita import hook useQuery dari TanStack Query.

//import hook useQuery
import { useQuery } from '@tanstack/react-query';

Kemudian kita import Link dari React Router.

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

Dan kita import service API yang kita buat sebelumnya.

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

Setelah itu, di dalam function component ProductIndex, kita melakukan fetch data menggunakan TanStack Query.

// 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;
}
});

Di atas, kita destruct fitur-fitur yang ada di dalam hook useQuery dari TanStack Query, yaitu data, isLoading, isError dan error.

const { data, isLoading, isError, error } = useQuery({

	//...
	
}

Di dalamnya, kita buat queryKey dengan nama products. Jika masih belum paham apa itu queryKey, maka berikut ini penjelasan singkatnya.

Apa itu queryKey ?

queryKey adalah identitas unik untuk query tertentu. Bisa berupa string saja ('products') atau array (['products']). Tujuan utama queryKey:

  • Menyimpan cache data berdasarkan key tersebut.
  • Menghindari konflik data jika ada query lain.
  • Menjadi acuan ketika ingin melakukan refetch atau invalidasi data.
// Set the query key
queryKey: ['products'],

Kemudian untuk queryFn, di dalamnya kita lakukan proses fetch ke backend melalui REST API dengan endpoint /api/products dan method yang digunakan adalah GET.

Apa Itu queryFn ?

queryFn (kepanjangan dari query function) adalah fungsi yang digunakan oleh TanStack Query untuk mengambil data dari API atau sumber data lainnya. Jadi setiap kali TanStack Query ingin melakukan fetch data, dia akan menjalankan fungsi ini.

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

Dan untuk menampilkan status seperti loading dan error, maka kita bisa gunakan kondisi seperti ini di dalam JSX.

{/* 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>
)}

Kemudian untuk menampilkan data-nya, kita tinggal lakukan iterasi atau loop data menggunakan function map dari JavaScript.

data.map((product) => (

	//...
	
))

Langkah 4 - Konfigurasi Route Products Index

Kita lanjutkan untuk membuat konfigurasi route-nya, sehingga nanti halama products bisa ditamilkan di dalam aplikasi.

Silahkan buka file src/routes/index.jsx, kemudian ubah kode-nya menjadi seperti berikut ini.

src/routes/index.jsx

// Import React Router
import { Routes, Route } from "react-router";

// Import view HomePage
import Home from "../views/home";

//import view ProductIndex
import ProductIndex from "../views/products/index";

// Definisikan component dengan (Functional Component)
const RoutesIndex = () => {
    return (
        <Routes>
            {/* Route untuk halaman utama */}
            <Route path="/" element={<Home />} />

            {/* Route untuk halaman produk */}
            <Route path="/products" element={<ProductIndex />} />
        </Routes>
    );
};

export default RoutesIndex;

Dari perubahan kode di atas, pertama kita import view products index.

// Import view ProductIndex
import ProductIndex from "../views/products/index";

Kemudian kita membuat konfigurasi route-nya.

{/* Route untuk halaman produk */}
<Route path="/products" element={<ProductIndex />} />

Langkah 5 - Uji Coba Menampilkan Data

Setelah semua berhasil dibuat, sekarang kita akan lakukan uji coba di dalam browser untuk melihat hasilnya, silahkan teman-teman klik menu PRODUCTS yang ada di navbar.

Atau bisa juga ke URL berikut ini http://localhost:5173/products, jika berhasil maka akan menampilkan hasil seperti berikut.

Kesimpulan

Pada artikel kali ini, kita telah belajar menggunakan useQuery dari TanStack Query, kita bisa menulis kode yang lebih ringkas, terstruktur, dan powerful. Tidak hanya lebih singkat, tapi juga memberikan manfaat besar seperti cache otomatis, loading/error handling bawaan, dan kemudahan untuk refetch data kapan saja.

Pada artikel selanjutnya, kita semua akan belajar bagaimana cara melakukan proses insert data di React menggunakan hook useMutation dari TanStack Query.

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