Tutorial Laravel 12 API Next JS 15 dan Tailwind CSS #9 Membuat Custom Hooks

Belajar membangun aplikasi fullstack modern dengan backend Laravel 12 RESTful API, frontend Next.js, dan desain menggunakan Tailwind CSS. Tutorial ini membahas step-by-step mulai dari setup environment, pembuatan API, konsumsi API di Next.js, hingga integrasi UI responsif.

✅ Telah dilihat 371 kali

Rating: 5.00 ⭐

... 13 August 2025, 20:33

React Hook

Ketika kita belajar React, salah satu konsep penting yang wajib dipahami adalah Hooks. Hooks diperkenalkan sejak React versi 16.8 sebagai cara baru untuk mengelola state dan lifecycle di dalam functional component.

Sebelum adanya Hooks, React mengenal dua jenis komponen:

  1. Class Component → bisa memiliki state dan lifecycle methods.
  2. Functional Component → hanya berupa fungsi sederhana yang menerima props dan mengembalikan JSX.

Masalahnya, functional component dulu sangat terbatas. Jika kita butuh state atau efek samping (seperti mengambil data API), kita terpaksa menggunakan class component. Hal ini membuat kode menjadi lebih panjang dan sulit dibaca.

Nah, React Hooks hadir untuk menyelesaikan masalah ini. Dengan Hooks, functional component menjadi lebih kuat karena sekarang bisa:

  • Menyimpan state (menggunakan useState)
  • Menangani efek samping (menggunakan useEffect)
  • Membuat logika reusable dengan custom hook
  • Dan banyak lagi (misalnya useContextuseReduceruseRef, dll.)

Kenapa Hooks Penting?

  1. Menyederhanakan kode – Kita bisa menulis komponen dengan sintaks fungsi biasa tanpa harus membuat class.
  2. Lebih mudah dibaca dan dirawat – Logika bisa dipisahkan ke dalam hook, sehingga UI dan logika tidak tercampur.
  3. Reusable – Kita bisa membuat custom hook untuk digunakan kembali di banyak komponen.
  4. Lebih sesuai dengan paradigma React modern – Karena banyak fitur terbaru React seperti Concurrent Mode dan Server Components dirancang agar bekerja optimal dengan hooks.

Dua Hook Paling Dasar

  1. useState → untuk menyimpan data yang bisa berubah. Contoh: jumlah klik tombol, isi input form, daftar produk.
  2. useEffect → untuk efek samping (side effects). Contoh: mengambil data dari API, mengatur timer, atau mengubah title halaman.

Membuat Custom Hooks

Silakan teman-teman tambahkan sebuah file baru dengan nama file useProducts.ts dan simpan didalam folder hooks. Silakan buka file tersebut kemudian masukkan kode berikut ini:

"use client"

import { useEffect, useState } from "react"
import { getProducts, createProduct, updateProduct, deleteProduct, Product, ProductPayload } from "@/services/products"

export function useProducts() {
  const [products, setProducts] = useState<Product[]>([])
  const [loading, setLoading] = useState(true)

  const fetchData = async () => {
    setLoading(true)
    try {
      const data = await getProducts()
      setProducts(data)
    } catch (err) {
      console.error("Gagal ambil data produk:", err)
    } finally {
      setLoading(false)
    }
  }

  const addProduct = async (payload: ProductPayload) => {
    await createProduct(payload)
    await fetchData()
  }

  const editProduct = async (id: number, payload: ProductPayload) => {
    await updateProduct(id, payload)
    await fetchData()
  }

  const removeProduct = async (id: number) => {
    await deleteProduct(id)
    await fetchData()
  }

  useEffect(() => {
    fetchData()
  }, [])

  return { products, loading, addProduct, editProduct, removeProduct }
}

Deklarasi Awal

"use client"

import { useEffect, useState } from "react"
import { getProducts, createProduct, updateProduct, deleteProduct, Product, ProductPayload } from "@/services/products"
  • use client → menandakan bahwa file ini adalah client component di Next.js (artinya berjalan di sisi browser, bukan server).
  • useEffect dan useState → dua hook bawaan React.
    • useState dipakai untuk menyimpan state (data produk, status loading).
    • useEffect dipakai untuk menjalankan efek samping, misalnya memanggil API saat komponen pertama kali dirender.
  • Import service: getProductscreateProductupdateProductdeleteProduct. Semua ini adalah fungsi untuk berkomunikasi dengan API produk.
  • Import tipe data Product dan ProductPayload. Ini membantu TypeScript mengenali struktur data produk.

Deklarasi State

const [products, setProducts] = useState<Product[]>([])
const [loading, setLoading] = useState(true)
  • products → array berisi daftar produk. Awalnya kosong [].
  • loading → penanda apakah data sedang diambil. Awalnya true karena saat pertama kali aplikasi dijalankan, kita menganggap data belum siap.

Fungsi fetchData (Ambil Data Produk)

const fetchData = async () => {
  setLoading(true)
  try {
    const data = await getProducts()
    setProducts(data)
  } catch (err) {
    console.error("Gagal ambil data produk:", err)
  } finally {
    setLoading(false)
  }
}
  • setLoading(true) → tandai bahwa proses ambil data sedang berjalan.
  • getProducts() → panggil API untuk ambil data produk.
  • setProducts(data) → simpan hasilnya ke state products.
  • Jika gagal, error akan dicetak ke console.
  • Di bagian finallysetLoading(false) → tandai bahwa proses sudah selesai, entah berhasil atau gagal.

Dengan pola ini, UI bisa menampilkan loading spinner saat data sedang dimuat.


Fungsi CRUD (Create, Update, Delete)

a. Menambah Produk

const addProduct = async (payload: ProductPayload) => {
  await createProduct(payload)
  await fetchData()
}
  • createProduct(payload) → panggil API untuk menambahkan produk baru.
  • Setelah berhasil, kita panggil fetchData() lagi agar daftar produk otomatis ter-update.

b. Mengedit Produk

const editProduct = async (id: number, payload: ProductPayload) => {
  await updateProduct(id, payload)
  await fetchData()
}
  • updateProduct(id, payload) → update data produk berdasarkan ID.
  • Lalu refresh data produk dengan fetchData().

c. Menghapus Produk

const removeProduct = async (id: number) => {
  await deleteProduct(id)
  await fetchData()
}
  • deleteProduct(id) → hapus produk berdasarkan ID.
  • Setelah itu, data di-refresh lagi.

Polanya sama: setiap kali ada perubahan data, kita panggil ulang fetchData() agar UI tetap sinkron dengan data terbaru.


useEffect (Panggil fetchData Pertama Kali)

useEffect(() => {
  fetchData()
}, [])
  • useEffect dengan dependency array kosong [] → artinya kode ini hanya dijalankan sekali saja ketika komponen pertama kali dirender.
  • Jadi, saat halaman dimuat, otomatis daftar produk langsung diambil dari API.

Return (Mengekspos State & Fungsi)

return { products, loading, addProduct, editProduct, removeProduct }

Hook ini mengembalikan:

  • products → daftar produk.
  • loading → status loading.
  • addProducteditProductremoveProduct → fungsi CRUD yang bisa dipakai oleh komponen lain.

Kesimpulan

useProducts adalah custom React hook yang mengelola seluruh alur CRUD produk.

  • Saat pertama kali dipanggil, ia otomatis mengambil data produk (fetchData).
  • State products dan loading disediakan agar UI bisa menampilkan daftar produk sekaligus status loading.
  • Ada tiga fungsi utama untuk manipulasi data: addProducteditProductremoveProduct.
  • Setiap kali ada perubahan, data akan disinkronkan ulang dengan memanggil fetchData().

Dengan pendekatan ini, kode di komponen UI menjadi lebih sederhana, karena semua logika pengelolaan data sudah disatukan di dalam hook.

🔥 Flash Sale


📜 Table Of Contents


📌 Daftar Episode


Daftar eBook