Pake React Hooks di proyek ReactJS kamu, kenapa nggak dari dulu ya
Oke, langsung aja kita bahas.
Pake React Hooks di proyek ReactJS kamu, kenapa nggak dari dulu ya. Iya, ini judul yang dalem banget buat yang udah pernah ngalamin pahit manisnya ngoding React pake class component. Dulu tuh, kayaknya ribet banget ya kalo mau ngurusin state, apalagi side effect kayak fetch data atau nge-set timer. Harus pake this.state
, this.setState
, terus ngebagiin logika di berbagai lifecycle method kayak componentDidMount
, componentDidUpdate
, componentWillUnmount
. Kadang pusing sendiri mana logic yang harusnya di mana, apalagi kalo komponennya udah mulai gede dan complex.
Nah, terus tiba-tiba muncul lah pahlawan namanya React Hooks di React 16.8. Jujur deh, awalnya mungkin skeptis atau males belajar lagi. Tapi setelah dicobain, sumpah deh, langsung mikir "wah, kenapa nggak dari dulu ya?". Hooks ini bener-bener ngerubah cara kita nulis komponen di React. Intinya, Hooks ini fungsi-fungsi keren yang bikin kita bisa "nempel" ke fitur-fitur React kayak state atau life cycle langsung dari functional component. Iya, nggak perlu lagi bikin class component cuma buat punya state atau pake lifecycle method. Komponen kita bisa tetep jadi fungsi sederhana tapi punya kekuatan yang sama, bahkan lebih gampang diatur.
Kenapa Hooks bisa bikin hidup kita lebih gampang dan ngoding lebih enak? Ada beberapa alasan utama:
- Code Jadi Lebih Simpel dan Rapi: Bye bye
this
yang kadang suka bikin bingung konteksnya. Bye bye boilerplate class component yang lumayan panjang. Dengan functional component dan Hooks, code kita jadi lebih ringkas, lebih mudah dibaca, dan alurnya lebih linear dari atas ke bawah. State dan logic yang berhubungan biasanya bisa ditaro deketan. - State Management Jadi Gampang: Inget dulu pake
this.state
danthis.setState
? Nah, sekarang adauseState
. Ini Hooks paling dasar dan sering dipake. Cara pakenya simple banget:const [stateValue, setStateValue] = useState(initialValue);
. Kamu langsung dapet variabel state-nya (stateValue
) dan fungsi buat update state-nya (setStateValue
). Jauh lebih intuitif kan? Nggak perlu lagi pusing samathis
dan nge-merge state secara manual (karenauseState
otomatis nge-replace state-nya, beda samathis.setState
di class yang nge-merge). - Ngatur Side Effect Jauh Lebih Terorganisir: Ini nih salah satu pain point terbesar di class component. Logic side effect kayak fetching data, nge-set subscription, atau manipulasi DOM itu kepencar di
componentDidMount
,componentDidUpdate
, dancomponentWillUnmount
. Akibatnya, logic yang sebenernya related (misalnya subscribe dan unsubscribe) jadi kepisah jauh. Nah, Hooks punyauseEffect
. Hooks ini didesain buat ngurusin side effect di functional component. Kerennya,useEffect
ini bisa ngurusin setup (kayak dicomponentDidMount
ataucomponentDidUpdate
) DAN cleanup (kayak dicomponentWillUnmount
) dalam satu tempat yang sama. Ini bikin code kita jadi lebih logis dan gampang dimengerti. Kamu tinggal bilang kapanuseEffect
ini harus jalan pake dependency array-nya. - Bisa Bikin dan Share Logic Sendiri (Custom Hooks): Ini superpower-nya Hooks! Kalau dulu kita mau reuse logic non-visual (kayak logic buat handle form input, nge-fetch data dengan state loading/error, atau toggle sesuatu), kita biasanya pake pattern render props atau higher-order components (HOCs). Pattern itu valid, tapi kadang bikin component tree jadi dalem banget alias "wrapper hell". Dengan Hooks, kita bisa bikin custom Hooks. Custom Hooks ini cuma fungsi JavaScript biasa kok yang namanya dimulai dengan
use
(misalnyauseToggle
,useFetch
,useLocalStorage
). Di dalemnya, kita bisa pake Hooks dasar lainnya (useState
,useEffect
, dll). Fungsi ini bisa nge-return state, fungsi buat update, atau apapun yang kita butuhin. Abis itu, custom Hooks ini bisa dipake di komponen manapun, bikin code kita jadi super reusable, modular, dan gampang ditest. Ini bener-bener game changer buat organisasi code di proyek gede. - Boilerplate Minimal: Udah disebutin sedikit, tapi ini penting. Nulis functional component + Hooks itu jauh lebih sedikit kodenya dibanding nulis class component buat fungsionalitas yang sama. Kurangnya boilerplate berarti kurangnya code yang perlu dibaca, dipahami, dan di-maintain.
- Lebih Gampang Ditest: Karena functional component dan Hooks kebanyakan cuma fungsi JavaScript biasa, mereka jadi lebih gampang ditest dibanding class component yang punya konteks
this
yang tricky.
Oke, sekarang kita masuk ke beberapa Hooks dasar yang WAJIB kamu pahami kalo mau nyemplung ke Hooksland:
useState
: Ini Hooks buat ngelola state lokal di komponen.
* Cara pakai: const [namaState, setNamaState] = useState(nilaiAwal);
* namaState
: Variabel buat nyimpen nilai state saat ini. * setNamaState
: Fungsi yang bisa kamu panggil buat update nilai state. Saat fungsi ini dipanggil, komponen akan re-render dengan nilai state yang baru. * nilaiAwal
: Nilai awal buat state kamu. Bisa apa aja (angka, string, boolean, object, array, null). Kalo nggak diisi, default-nya undefined
. * Tips Update State: Kalo update state-nya tergantung sama nilai state sebelumnya (misalnya counter setCount(count + 1)
), lebih baik pake functional update: setCount(prevCount => prevCount + 1);
. Ini ngehindarin race condition kalo update-nya async atau ada banyak update berdekatan. * Contoh: const [isVisible, setIsVisible] = useState(false);
atau const [items, setItems] = useState([]);
useEffect
: Hooks buat ngurusin side effect. Think of it as a combination ofcomponentDidMount
,componentDidUpdate
, andcomponentWillUnmount
.
* Cara pakai: useEffect(() => { // code side effect di sini }, [dependencyArray]);
* Callback Function: Fungsi pertama itu tempat kamu nulis code side effect. Ini bakal dijalanin React setelah DOM di-render. * Cleanup Function: Kalo side effect-nya butuh cleanup (misalnya nge-clear timer, unsubscribe event listener), kamu bisa return sebuah fungsi dari callback pertama tadi: useEffect(() => { // setup side effect return () => { // cleanup di sini }; }, [dependencyArray]);
. Fungsi yang di-return ini bakal dijalanin sebelum komponen unmount atau sebelum useEffect
dijalanin lagi karena dependency berubah. * Dependency Array: Argumen kedua (array). Ini PENTING BANGET. Array ini ngasih tau React kapan useEffect
kamu harus dijalanin lagi. * Nggak pake array: useEffect(() => { ... });
-> Efek bakal dijalanin setiap kali komponen re-render. Jarang dipake, bisa bikin infinite loop kalo nggak hati-hati. Array kosong []
: useEffect(() => { ... }, []);
-> Efek cuma dijalanin sekali* setelah render pertama, kayak componentDidMount
. Cleanup (jika ada) bakal dijalanin saat komponen unmount. Cocok buat fetch data awal atau setup event listener global. Array dengan nilai: useEffect(() => { ... }, [prop1, stateA]);
-> Efek bakal dijalanin saat render pertama DAN setiap kali nilai prop1
atau stateA
berubah. Cleanup bakal dijalanin sebelum efek dijalanin lagi dan saat komponen unmount. Ini yang paling sering dipake, memastikan efek berjalan hanya* saat yang dibutuhkan. * Tips useEffect
: Pastikan dependency array kamu bener. ESLint punya plugin eslint-plugin-react-hooks
yang ngebantu banget ngecek ini secara otomatis. Pisah-pisah useEffect
kamu berdasarkan concern-nya. Jangan tumpuk semua side effect jadi satu useEffect
kalo logic-nya beda-beda. Misalnya, satu useEffect
buat fetch data, satu lagi buat ngeset title dokumen.
useContext
: Hooks buat ngakses nilai dari React Context. Jadi lebih gampang dibanding pakeContext.Consumer
ataucontextType
di class component.
* Cara pakai: const value = useContext(NamaContextKamu);
* Kamu tinggal panggil useContext
dengan Context object yang udah kamu bikin (React.createContext
). Hooks ini bakal nge-return nilai dari Context yang paling deket di component tree di atas komponen kamu.
useReducer
: Alternatif buatuseState
kalo logic update state kamu udah mulai kompleks atau state-nya punya banyak sub-nilai yang related. Mirip kayak konsep Redux (punya reducer dan dispatch action), tapi buat state lokal komponen.
* Cara pakai: const [state, dispatch] = useReducer(reducer, initialState);
* reducer
: Fungsi yang nerima state saat ini dan sebuah action, terus ngasih return state yang baru. * initialState
: Nilai awal buat state-nya. * state
: Nilai state saat ini (sama kayak yang di useState
). * dispatch
: Fungsi yang kamu panggil buat "ngirim action" ke reducer buat update state. * Kapan pake useReducer
? Kalo update state kamu melibatkan logic yang complex, state kamu punya struktur nested, atau kalo beberapa update state terjadi berurutan dan saling tergantung. Buat state yang simple (boolean, string, number), useState
udah lebih dari cukup.
useRef
: Hooks yang nge-return object mutable yang nilai current
-nya bakal persist selama lifecycle komponen, TAPI nggak* bakal menyebabkan re-render saat nilai current
-nya berubah. Berguna buat: * Nyimpen nilai yang butuh persist tapi nggak perlu bikin UI update (contoh: timer ID, previous value dari state/prop). * Ngakses elemen DOM secara langsung (mirip React.createRef()
di class component). * Cara pakai: const refContainer = useRef(initialValue);
* Kamu ngakses nilainya pake refContainer.current
.
useCallback
danuseMemo
: Hooks buat optimasi performa. Ini mungkin nggak kamu butuhin di awal, tapi penting banget buat komponen yang sering re-render atau nerima props yang complex.
* useCallback
: Memoizes (mengingat) sebuah fungsi. * Cara pakai: const memoizedCallback = useCallback(() => { // fungsi kamu }, [dependencies]);
* Berguna banget kalo kamu passing callback function ke child component yang udah dioptimasi pake React.memo
. Tanpa useCallback
, fungsi baru bakal dibuat di setiap render, bikin React.memo
di child component nggak guna karena prop function-nya selalu dianggap baru. Dengan useCallback
, fungsi yang sama bakal di-pass selama dependensinya nggak berubah. * useMemo
: Memoizes (mengingat) sebuah nilai yang dihitung dari sebuah fungsi. * Cara pakai: const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
* Berguna kalo kamu punya perhitungan yang mahal/lama dan hasilnya cuma butuh dihitung ulang kalo input/dependensinya berubah. Nilai yang di-return dari fungsi pertama bakal disimpan, dan fungsi itu cuma dijalanin ulang kalo dependency array-nya berubah.
Aturan Main (Rules of Hooks): Ini Mutlak!
React Hooks punya dua aturan simpel tapi krusial yang HARUS kamu ikutin:
- Panggil Hooks cuma di Top Level: Jangan pernah panggil Hooks di dalem loop, kondisi (
if
), atau nested function lainnya. Hooks HARUS dipanggil di level teratas dari functional component atau custom Hooks. Alasannya? React mengandalkan urutan pemanggilan Hooks setiap kali komponen re-render buat nyimpen state atau efek yang bener. Kalo urutannya berubah karena kondisi atau loop, React bingung. - Panggil Hooks cuma dari React Functions: Panggil Hooks cuma dari functional component React atau dari custom Hooks buatan kamu sendiri. Jangan panggil Hooks dari regular JavaScript functions atau dari class component.
Nglanggar aturan ini bisa bikin bug yang susah dilacak. Makanya, pake eslint-plugin-react-hooks
itu sangat disarankan. Dia bakal nge-scan code kamu dan ngasih peringatan kalo kamu ngelanggar aturan Hooks.
Membuat Custom Hooks Sendiri: Nambah Kekuatan!
Seperti yang udah dibahas, custom Hooks itu cara paling powerful buat reuse logic antar komponen. Gampang banget bikinnya:
- Buat fungsi JavaScript biasa.
- Kasih nama fungsi itu dengan prefix
use
(contoh:useToggle
,useWindowSize
,useFetch
). - Di dalem fungsi itu, kamu bisa pake Hooks dasar lainnya (
useState
,useEffect
,useContext
,useRef
, dll). - Return apapun yang kamu butuhin dari Hooks itu (bisa array kayak
useState
, object, atau nilai tunggal).
Contoh sederhana custom Hooks useToggle
:
javascript
import { useState } from 'react';function useToggle(initialValue = false) {
const [isOn, setIsOn] = useState(initialValue);const toggle = () => setIsOn(prev => !prev);return [isOn, toggle]; // Return state dan fungsi untuk mengganti
}// Cara pakenya di komponen lain:
// function MyComponent() {
// const [isModalOpen, toggleModal] = useToggle(false);
//
// return (
//
// Open Modal
// {isModalOpen && Isi Modal...}
//
// );
// }
See? Logic buat toggle state jadi reusable. Kamu bisa pake useToggle
di komponen manapun yang butuh fitur toggle. Ini bikin code kamu DRY (Don't Repeat Yourself) dan gampang di-maintain.
Tips Tambahan Buat yang Baru Mulai atau Lagi Migrasi:
- Mulai dari Komponen Baru: Kalo kamu punya proyek eksisting pake class component, nggak harus langsung ganti semua. Mulai aja pake Hooks buat komponen-komponen baru. Hooks dan class component bisa hidup berdampingan dalam satu proyek.
- Migrasi Bertahap: Kalo mau migrasi class component ke Hooks, mulai dari komponen yang paling sederhana yang nggak punya banyak state atau side effect. Terus lanjut ke yang lebih kompleks. Jangan terburu-buru.
- Baca Dokumentasi Resmi React: Dokumentasi Hooks di website React itu luar biasa lengkap dan jelas. Baca "Introducing Hooks" dan "Hooks at a Glance".
- Latihan, Latihan, Latihan: Kayak skill ngoding lainnya, kunci mahir Hooks ya dengan banyak latihan. Coba implementasi ulang fungsionalitas yang biasa kamu bikin pake class component tapi sekarang pake Hooks. Bikin custom Hooks sederhana.
- Pake Linters: Sekali lagi, install
eslint-plugin-react-hooks
dan aktifin di proyek kamu. Ini penyelamat banget dari kesalahan Hooks yang umum.
Potensi Masalah Umum (dan Cara Ngatasinnya):
- Dependency Array yang Salah: Ini paling sering kejadian. Kalo dependency array-nya nggak lengkap,
useEffect
kamu bisa nggak jalan saat seharusnya jalan, atau pake nilai state/prop yang udah usang (stale closure). Kalo terlalu lengkap,useEffect
bisa jalan terlalu sering. Solusinya: install linter Hooks, atau kalo masih bingung, coba pake dependency array kosong dulu terus bertahap tambahin dependency yang dibutuhkan sampe linternya diem.
State Updates Nggak Langsung: Inget, update state via setNamaState
itu asynchronous (mirip this.setState
). React nge-batch update state buat optimasi performa. Jadi, kalo kamu langsung baca nilai state setelah manggil setter-nya di baris berikutnya, kamu mungkin masih dapet nilai state yang lama. Kalo butuh logic yang jalan setelah* state ke-update, pake useEffect
dengan state tersebut di dependency array-nya, atau pake functional update di setter-nya.
- Lupa Aturan Hooks: MangkinHooks di dalam
if
atau loop. Ini bakal bikin error atau perilaku yang aneh. Solusinya: Ikutin aturan Rules of Hooks dengan disiplin tinggi, dan pake linter.
Jadi, kesimpulannya, Hooks ini bukan cuma fitur baru, tapi bener-bener cara baru yang lebih modern, efisien, dan menyenangkan buat nulis komponen React. Mereka bikin code kita lebih bersih, lebih reusable lewat custom Hooks, dan ngatur state serta side effect jadi jauh lebih intuitif dibanding class component. Kalo kamu masih pake class component, nggak ada salahnya kok, tapi nguasain Hooks ini bakal jadi skill wajib buat proyek React ke depannya. Nggak heran banyak developer yang ngerasa "kenapa nggak dari dulu ya" setelah nyobain Hooks. Yuk, buruan dicoba dan rasain sendiri bedanya! Happy coding!