K

Command Palette

Search for a command to run...

Daftar

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:

  1. useContext: Buat ngoper data "jauh" tanpa perlu ngirim props lewat banyak level komponen (solusi buat prop drilling).
  2. 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:

    1. Bikin Context: Kamu bikin "wadah" data global pake React.createContext().
    2. 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.
    3. Konsumsi Nilai (Consumer/useContext): Komponen child (atau cucu, cicit, dll.) yang butuh data itu bisa ngaksesnya pake hook useContext(NamaContext).
  • 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.

Contoh Konseptual useContext (Sangat Disederhanakan):

jsx
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:
    1. Bikin ref: const namaRef = useRef(null);
    2. Pasang ref itu ke atribut ref di elemen JSX: <input ref={namaRef} type="text" />
    3. Setelah komponen di-render, namaRef.current bakal nunjuk ke objek elemen DOM asli dari input itu. Kamu bisa manggil metode DOM biasa di namaRef.current (misal, namaRef.current.focus()).

Contoh useRef buat Fokus ke Input:

jsx
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 atau setTimeout biar bisa di-clearInterval atau clearTimeout nanti. Kalau kamu simpen ID ini di state useState, setiap kali ID-nya (yang cuma angka) di-set, komponenmu bakal re-render gak perlu.
  • Dengan useRef, kamu bisa nyimpen nilai itu di namaRef.current. Nilai namaRef.current ini bakal tetep ada (persistent) antar render, tapi ngubahnya gak bakal bikin komponen re-render.

Contoh useRef buat Nyimpen ID Interval:

jsx
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`?