Hooks React Lainnya (useContext, useRef)
Selain useState dan useEffect, kenalan singkat dengan React Hooks lain yang berguna: `useContext` untuk menghindari prop drilling dan `useRef` untuk akses DOM langsung atau nilai mutable.
Gak Cuma useState
& useEffect
: Ngintip Hooks React Keren Lainnya!
Udah mulai jago pake useState
buat ngelola data komponen dan useEffect
buat ngurusin side effects? Keren! Dua hook itu emang fondasi banget di React. Tapi, React masih punya beberapa "jurus" hook lain yang bisa ngebantu kita ngatasin masalah-masalah spesifik dengan cara yang lebih elegan.
Di bagian ini, kita bakal kenalan singkat sama dua hook lain yang lumayan sering kepake:
useContext
: Buat ngoper data "jauh" tanpa perlu ngirim props lewat banyak level komponen (solusi buat prop drilling).useRef
: Buat "megang" referensi ke elemen DOM asli atau buat nyimpen nilai mutable yang gak nge-trigger re-render.
Ini cuma pengenalan konsep ya, biar kamu tau ada alat ini. Penggunaannya yang lebih dalem bisa kamu eksplorasi nanti pas udah makin nyaman sama React.
1. useContext
: Ngoper Data "Antar Galaxy" Tanpa Capek Nge-Props!
Kamu pasti inget kan pola "Lifting State Up"? Itu bagus banget buat nge-share state antara beberapa komponen. Tapi, gimana kalau state itu ada di komponen paling atas (misal, di App
), terus ada komponen cicit atau canggah di paling bawah yang butuh data itu? Kamu jadi harus ngoper prop itu lewat semua level komponen di antaranya, padahal komponen-komponen di tengah itu mungkin gak butuh data itu sama sekali. Ini namanya Prop Drilling, dan bisa bikin kode jadi ribet.
Nah, React Context API (yang dipake bareng hook useContext
) nyediain cara buat ngirim data "langsung" ke komponen mana pun di bawah pohon komponen tertentu, tanpa perlu ngoper props manual lewat tiap level.
-
Konsep Dasar Context:
- Bikin Context: Kamu bikin "wadah" data global pake
React.createContext()
. - Sediain Nilai (Provider): Komponen parent yang punya data itu bakal "ngebungkus" bagian pohon komponen anaknya pake
<NamaContext.Provider value={dataYangMauDishare}>
. Semua komponen di dalem Provider ini bisa "ngintip" data itu. - Konsumsi Nilai (Consumer/useContext): Komponen child (atau cucu, cicit, dll.) yang butuh data itu bisa ngaksesnya pake hook
useContext(NamaContext)
.
- Bikin Context: Kamu bikin "wadah" data global pake
-
Kapan
useContext
Berguna?- Buat data yang emang bener-bener "global" di sebagian besar aplikasimu, misalnya:
- Tema aplikasi (light/dark mode).
- Informasi pengguna yang lagi login.
- Preferensi bahasa.
- Buat ngindarin prop drilling yang udah keterlaluan.
- Buat data yang emang bener-bener "global" di sebagian besar aplikasimu, misalnya:
Contoh Konseptual useContext
(Sangat Disederhanakan):
import React, { useState, useContext, createContext } from 'react'; // Import createContext
// 1. Bikin Context
const ThemeContext = createContext('light'); // Nilai default 'light'
// 3. Komponen Child/Cucu yang mengonsumsi Context
function TombolTema() {
const { tema, toggleTema } = useContext(ThemeContext); // Akses data dari context!
return (
<button onClick={toggleTema} style={{ margin: '10px' }}>
Ganti ke Mode {tema === 'light' ? 'Gelap' : 'Terang'}
</button>
);
}
function KontenLain() {
const { tema } = useContext(ThemeContext);
return <p style={{ padding: '10px', border: `1px solid ${tema === 'light' ? 'black' : 'white'}` }}>Ini konten lain yang juga pakai tema.</p>;
}
// 2. Komponen Parent yang menyediakan nilai
function AppWithTheme() {
const [tema, setTema] = useState('light');
const toggleTema = () => setTema(t => (t === 'light' ? 'dark' : 'light'));
const appStyle = {
background: tema === 'light' ? '#fff' : '#333',
color: tema === 'light' ? '#000' : '#fff',
padding: '20px',
border: '1px solid #ccc'
};
return (
// Sediakan nilai context ke semua anak di bawah Provider ini
<ThemeContext.Provider value={{ tema, toggleTema }}>
<div style={appStyle}>
<h1>Aplikasi dengan Tema</h1>
<TombolTema />
<KontenLain />
</div>
</ThemeContext.Provider>
);
}
// Komponen utama yang akan dirender (misalnya di App.jsx atau untuk demo)
function DemoContext() {
return <AppWithTheme />;
}
export default DemoContext;
// Atau jika ini bagian dari App.jsx yang lebih besar, sesuaikan cara render DemoContext
Di contoh ini, TombolTema
bisa langsung dapet nilai tema
dan fungsi toggleTema
tanpa perlu dioper lewat props dari App
ke KontenLain
(kalau TombolTema
ada di dalem KontenLain
).
Perhatian: useContext
itu bagus buat ngindarin prop drilling, tapi jangan dipake buat semua state ya. Kalau state-nya cuma dipake sama beberapa komponen yang deketan, lifting state up biasa masih jadi pilihan yang lebih simpel. useContext
lebih cocok buat state yang bener-bener global atau di-share ke banyak level. Untuk state management yang lebih kompleks lagi, orang biasanya pake library kayak Redux, Zustand, atau Jotai.
2. useRef
: "Megang" Elemen DOM atau Nilai yang Gak Bikin Re-render
Hook useRef
ini punya dua kegunaan utama yang agak beda:
a. Ngakses Elemen DOM Secara Langsung
Kadang, kita perlu ngakses elemen DOM HTML asli langsung dari kode JavaScript kita, misalnya buat:
- Ngefokusin input field secara otomatis.
- Ngejalanin animasi imperatif.
- Ngukur ukuran atau posisi elemen.
- Integrasi sama library DOM pihak ketiga.
Di React, kita hindari manipulasi DOM manual sebisa mungkin karena React yang ngurusin itu. Tapi, buat kasus-kasus di atas, useRef
bisa jadi "jembatan"-nya.
- Cara Kerja:
- Bikin ref:
const namaRef = useRef(null);
- Pasang ref itu ke atribut
ref
di elemen JSX:<input ref={namaRef} type="text" />
- Setelah komponen di-render,
namaRef.current
bakal nunjuk ke objek elemen DOM asli dari input itu. Kamu bisa manggil metode DOM biasa dinamaRef.current
(misal,namaRef.current.focus()
).
- Bikin ref:
Contoh useRef
buat Fokus ke Input:
import React, { useRef, useEffect } from 'react';
function FormFokusOtomatis() {
const inputRef = useRef(null); // 1. Bikin ref
useEffect(() => {
// 3. Akses elemen DOM lewat .current dan panggil metode focus()
// Efek ini jalan setelah render pertama
inputRef.current.focus();
}, []); // Array dependensi kosong biar cuma jalan sekali pas mount
return (
<div>
<label htmlFor="nama">Nama:</label>
{/* 2. Pasang ref ke input */}
<input ref={inputRef} type="text" id="nama" />
<button onClick={() => inputRef.current.value = "Direset via Ref!"}>Reset Pake Ref</button>
</div>
);
}
export default FormFokusOtomatis;
PENTING: Ngubah DOM langsung pake ref (kayak inputRef.current.value = ...
) itu bypassing React punya mekanisme update. Ini bisa dipake buat kasus tertentu, tapi kalau bisa, selalu usahakan ngelola UI lewat state dan props buat ngejaga alur data React.
b. Nyimpen Nilai Mutable yang Gak Memicu Re-render
Kegunaan kedua useRef
(yang kadang kurang diketahui pemula) adalah buat nyimpen nilai apa pun yang bisa berubah (mutable) tapi perubahannya itu GAK PERLU micu re-render komponen.
- Bayangin kamu butuh nyimpen ID dari
setInterval
atausetTimeout
biar bisa di-clearInterval
atauclearTimeout
nanti. Kalau kamu simpen ID ini di stateuseState
, setiap kali ID-nya (yang cuma angka) di-set, komponenmu bakal re-render gak perlu. - Dengan
useRef
, kamu bisa nyimpen nilai itu dinamaRef.current
. NilainamaRef.current
ini bakal tetep ada (persistent) antar render, tapi ngubahnya gak bakal bikin komponen re-render.
Contoh useRef
buat Nyimpen ID Interval:
import React, { useState, useEffect, useRef } from 'react';
function Stopwatch() {
const [detik, setDetik] = useState(0);
const [isRunning, setIsRunning] = useState(false);
const intervalIdRef = useRef(null); // Buat nyimpen ID interval
useEffect(() => {
if (isRunning) {
intervalIdRef.current = setInterval(() => { // Simpen ID interval ke .current
setDetik(d => d + 1);
}, 1000);
} else {
clearInterval(intervalIdRef.current); // Hentikan interval pake ID yang disimpen
}
// Cleanup pas unmount
return () => clearInterval(intervalIdRef.current);
}, [isRunning]); // Efek jalan ulang kalau isRunning berubah
return (
<div>
<p>Stopwatch: {detik} detik</p>
<button onClick={() => setIsRunning(!isRunning)}>
{isRunning ? "Pause" : "Start"}
</button>
<button onClick={() => { setIsRunning(false); setDetik(0); }}>
Reset
</button>
</div>
);
}
export default Stopwatch;
Di sini, intervalIdRef.current
dipake buat nyimpen ID interval tanpa bikin re-render pas ID-nya di-set.
useContext
dan useRef
ini adalah dua hook tambahan yang ngebuka banyak kemungkinan di React.
useContext
bantu kamu ngelola state "global" atau nge-share data tanpa prop drilling yang berlebihan.useRef
ngasih kamu "pintu darurat" buat ngakses DOM kalau emang bener-bener perlu, atau cara buat nyimpen nilai yang gak terkait sama rendering.
Buat awal, mungkin kamu bakal lebih sering pake useState
dan useEffect
. Tapi, seiring aplikasimu makin kompleks, dua hook ini (useContext
dan useRef
) pasti bakal kepake juga!
Kuis Hooks React Lainnya (useContext, useRef)
Pertanyaan 1 dari 5
Apa masalah utama yang coba diatasi oleh React Context API yang digunakan bersama hook `useContext`?