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