useContext: esensi, hook akses ke konteks dan provider di React

Penulis: IT Sectr Diterbitkan: 2026-07-04 Waktu membaca: 9 mnt

useContext — adalah hook React yang memberikan komponen fungsional akses langsung ke data dari konteks yang dibuat melalui createContext. Konteks di React memecahkan masalah props drilling — pengiriman props melalui banyak komponen perantara yang sendiri tidak menggunakan data tersebut. Menurut React Documentation (2025), useContext menerima objek konteks dan mengembalikan nilai saat ini yang ditetapkan oleh Provider terdekat di atas pohon komponen. Ketika nilai di Provider berubah, semua komponen yang menggunakan useContext secara otomatis me-render ulang.

Poin Penting

  • useContext — hook untuk membaca nilai dari konteks React tanpa props drilling.
  • createContext — membuat objek konteks dengan nilai default dan komponen Provider.
  • Provider — komponen pembungkus yang mengirimkan nilai konteks ke semua elemen anak.
  • Render ulang — perubahan nilai di Provider menyebabkan render ulang semua konsumen konteks.
  • Melewati komponen perantara — useContext memungkinkan pengiriman data melalui beberapa tingkat penyarangan.

Apa itu useContext di React

useContext — adalah hook yang ditambahkan di React 16.8 bersama dengan hook lainnya, yang memungkinkan Anda membaca nilai dari konteks React. Konteks adalah mekanisme bawaan di React yang dirancang untuk mengirimkan data melalui pohon komponen tanpa perlu mengirim props secara manual di setiap level. useContext menggantikan komponen Consumer dari Context API lama dan membuat kode lebih ringkas dan mudah dibaca.

Skenario penggunaan konteks yang umum meliputi tema desain (terang/gelap), pengaturan regional dan terjemahan (i18n), autentikasi pengguna, pengaturan aplikasi, dan data global lainnya yang dibutuhkan oleh banyak komponen di berbagai tingkat penyarangan. Tim React merekomendasikan penggunaan konteks untuk data yang bersifat global untuk sub-pohon komponen, tetapi tidak untuk seluruh aplikasi.

Menurut React Team — Context documentation (2025), penggunaan konteks yang tidak tepat adalah salah satu penyebab utama masalah kinerja di aplikasi React. Setiap perubahan nilai di Provider menyebabkan render ulang semua konsumen, terlepas dari bagian data mana yang berubah. Optimalisasi melalui useMemo dan pemisahan konteks memecahkan masalah ini.

jsx
import { createContext, useContext } from 'react';

// Buat konteks dengan nilai default
const ThemeContext = createContext('terang');

function ThemedButton() {
    const theme = useContext(ThemeContext);
    return <button className={`btn-${theme}`}>Click</button>;
}

Bagaimana konteks bekerja di React

Mekanisme konteks di React diimplementasikan melalui pola Provider-Consumer. createContext mengembalikan objek dengan dua entitas: Provider — komponen yang mengirimkan nilai, dan objek konteks itu sendiri yang digunakan di useContext. Provider dipasang di pohon komponen dan mengirimkan nilai ke semua elemen anak terlepas dari kedalaman penyarangan.

Ketika React menemukan panggilan useContext, ia bergerak naik melalui pohon fiber untuk mencari Provider terdekat untuk konteks tersebut. Jika Provider ditemukan, nilainya dikembalikan. Jika Provider tidak ditemukan, nilai default yang dikirimkan ke createContext dikembalikan. Pencarian ini terjadi pada setiap render, tetapi berkat memoisasi node fiber sangat cepat dan tidak mempengaruhi kinerja.

Menurut React — Context internals (2024), implementasi internal useContext menggunakan daftar terkait dari hook, mirip dengan useState. Setiap hook menyimpan referensi ke node fiber, yang memungkinkan React dengan cepat menentukan Provider mana yang sesuai dengan konteks tersebut. Jika Provider memperbarui nilai, React menandai semua node fiber yang menggunakan konteks ini untuk render ulang.

Provider dan konteks bersarang

Komponen Provider dapat disarangkan satu sama lain, menciptakan hierarki konteks. Setiap Provider anak mengganti nilai induk untuk sub-pohonnya. Ini berguna ketika di satu layar diperlukan tema terang, dan di jendela modal bersarang — tema gelap. useContext selalu mengembalikan nilai Provider terdekat di atas pohon.

jsx
const UserContext = createContext(null);
const ThemeContext = createContext('terang');

function App() {
    return (
        <UserContext.Provider value={{ name: 'Alice' }}>
            <ThemeContext.Provider value='dark'>
                <Profile />
            </ThemeContext.Provider>
        </UserContext.Provider>
    );
}

Membuat provider dengan createContext

Fungsi createContext(defaultValue) membuat objek konteks. Parameter defaultValue digunakan ketika komponen memanggil useContext, tetapi di atas pohon tidak ada Provider yang sesuai. Tanpa defaultValue, useContext akan mengembalikan undefined, yang dapat menyebabkan kesalahan tak terduga. Disarankan untuk selalu mengirimkan nilai default yang bermakna atau null.

Membuat provider kustom adalah pola umum untuk enkapsulasi logika konteks. Di dalam provider semacam itu, status disimpan (melalui useState atau useReducer) dan disediakan melalui prop value dari Provider. Ini memungkinkan menyembunyikan detail implementasi dari komponen konsumen dan memusatkan logika manajemen konteks di satu tempat.

jsx
// Provider kustom dengan manajemen status
const AuthContext = createContext(null);

function AuthProvider({ children }) {
    const [user, setUser] = useState(null);

    const login = useCallback(async (email, pass) => {
        const u = await loginApi(email, pass);
        setUser(u);
    }, []);

    return (
        <AuthContext.Provider value={{ user, login }}>
            {children}
        </AuthContext.Provider>
    );
}

Menggunakan useContext di komponen anak

Di komponen fungsional, useContext adalah satu-satunya cara untuk mendapatkan akses ke konteks. Ini menggantikan komponen Consumer dari Context API lama yang memerlukan pola render-prop: <ThemeContext.Consumer>{value => ...}</ThemeContext.Consumer>. useContext membuat kode lebih linier dan mudah dibaca, terutama saat bekerja dengan beberapa konteks dalam satu komponen.

Saat menggunakan beberapa konteks dalam satu komponen, cukup panggil useContext beberapa kali untuk setiap konteks. Setiap panggilan mengembalikan nilai Provider yang sesuai. Urutan panggilan tidak penting, karena setiap konteks adalah entitas independen. React mengoptimalkan beberapa panggilan melalui sistem referensi fiber yang sama.

jsx
function Dashboard() {
    const { user } = useContext(AuthContext);
    const theme = useContext(ThemeContext);
    const { locale } = useContext(I18nContext);

    return (
        <div className={`dashboard-${theme}`}>
            <h1>{locale.greeting}, {user.name}</h1>
        </div>
    );
}

useContext vs Redux: kapan memilih apa

Pilihan antara useContext dan Redux tergantung pada skala dan kompleksitas manajemen status. useContext + useReducer adalah pengganti ringan untuk Redux untuk aplikasi kecil dan menengah. Tidak memerlukan instalasi pustaka eksternal, lebih mudah dipelajari, dan cukup untuk sebagian besar tugas. Redux digunakan ketika diperlukan arsitektur ketat dengan middleware, alat pengembang, dan pembaruan yang tidak dapat diubah.

Keuntungan utama Redux dibandingkan useContext adalah optimalisasi render ulang. Secara default, ketika nilai di Provider berubah, semua konsumen konteks me-render ulang. Redux dengan useSelector dan shallowEqual memungkinkan komponen untuk berlangganan hanya ke bagian tertentu dari status, yang secara signifikan mengurangi jumlah render ulang di aplikasi besar. Konteks juga dapat dioptimalkan dengan membaginya menjadi banyak konteks kecil.

KriteriauseContextRedux
KompleksitasTidak ada dependensi eksternalMemerlukan konfigurasi store dan middleware
Render ulangSemua konsumen pada setiap perubahanHanya yang berlangganan ke slice tertentu
DevToolsReact DevToolsRedux DevTools dengan time-travel
MiddlewareTidak didukungRedux Thunk, Saga, Observable
Kapan memilihAplikasi menengah, 3-5 konteksAplikasi besar dengan logika bisnis kompleks

Menurut Redux maintainers — When to use Redux (2024), 70% aplikasi React tidak memerlukan Redux. Jika Anda memiliki kurang dari 50 komponen dan status tidak memiliki logika kompleks dengan caching, debounce, dan efek samping — useContext + useReducer sudah lebih dari cukup. Redux menambah boilerplate dan harus digunakan secara sadar.

Kesalahan umum dengan useContext

Kesalahan paling umum adalah pembuatan ulang objek value pada setiap render Provider. Jika Anda mengirimkan value={{ user, login }} ke Provider, pada setiap render Provider objek baru dibuat, yang menyebabkan render ulang semua konsumen, bahkan jika data tidak berubah. Solusinya — memoisasi value melalui useMemo atau menggunakan konteks terpisah untuk data yang sering dan jarang berubah.

  • Render ulang berlebihan — objek value baru pada setiap render Provider. Gunakan useMemo untuk memoisasi value.
  • Konteks terlalu besar — satu Provider dengan puluhan bidang menyebabkan semua komponen anak me-render ulang saat bidang apa pun berubah. Bagi menjadi beberapa konteks berdasarkan makna.
  • Tidak ada defaultValue — jika Provider tidak ditemukan, useContext mengembalikan defaultValue, dan jika undefined — setiap panggilan akan gagal dengan TypeError.
  • Provider bersarang dari tipe yang sama — penimpaan konteks di level dalam dapat membingungkan dan menyebabkan nilai tak terduga.
jsx
// ❌ Objek baru pada setiap render — semua konsumen me-render ulang
<AuthContext.Provider value={{ user, login }}>{children}</AuthContext.Provider>

// ✅ Nilai yang dimemoisasi — render ulang hanya ketika pengguna atau login berubah
const authValue = useMemo(() => ({ user, login }), [user, login]);
<AuthContext.Provider value={authValue}>{children}</AuthContext.Provider>

Untuk mengatasi masalah “konteks besar”, bagi status global ke dalam grup logis: AuthContext, ThemeContext, I18nContext. Setiap konteks bertanggung jawab atas domainnya sendiri dan diperbarui secara independen. Ini lebih sederhana daripada mencoba mengoptimalkan satu konteks raksasa melalui useMemo dan memberikan perilaku render ulang yang lebih dapat diprediksi.

Pertanyaan yang Sering Diajukan

Bisakah saya mengubah konteks dari komponen anak?

Ya, jika Anda mengirimkan fungsi mutator ke value Provider. Pola umum adalah menyimpan status di Provider dan mengirimkan baik data maupun fungsi untuk memperbaruinya melalui useContext. Komponen anak memanggil fungsi-fungsi ini, dan perubahan status di Provider secara otomatis memperbarui semua konsumen. Ini adalah pengganti dasar untuk Redux di aplikasi kecil.

Mana yang lebih cepat — useContext atau Redux?

Untuk skenario sederhana, useContext lebih cepat karena tidak ada overhead dari store dan middleware. Tetapi pada pembaruan yang sering dengan banyak konsumen, Redux unggul karena selektornya (useSelector) berlangganan ke bagian status tertentu, sementara useContext me-render ulang semua konsumen pada setiap perubahan. Untuk aplikasi dengan frekuensi pembaruan tinggi (animasi, real-time) pilihan harus jatuh pada Redux atau pustaka khusus.

Bisakah saya menggunakan useContext di luar komponen React?

Tidak. useContext, seperti semua hook, hanya dapat dipanggil di dalam komponen fungsional React atau hook kustom. Jika Anda perlu mendapatkan nilai konteks di fungsi biasa (misalnya, di utilitas atau layanan), kirimkan sebagai parameter dari komponen atau gunakan modul terpisah dengan status global di luar React.

Bagaimana cara kerja useContext dengan TypeScript?

Pengetikan konteks di TypeScript — menentukan tipe di createContext: createContext<AuthContextType | null>(null). Ini menjamin bahwa useContext(AuthContext) mengembalikan nilai dengan tipe yang benar. Pola yang nyaman adalah membuat hook kustom useAuth yang memanggil useContext, memeriksa null, dan memberikan kesalahan yang mudah dipahami: “useAuth must be used within AuthProvider”.

Mengapa useContext mengembalikan undefined meskipun Provider ada?

Penyebab paling umum adalah komponen konsumen berada di luar Provider yang sesuai. Periksa apakah Provider membungkus seluruh sub-pohon tempat useContext digunakan. Penyebab kedua adalah Provider dikirimkan ke objek konteks yang berbeda: pengembang membuat konteks melalui panggilan createContext, tetapi menggunakan useContext dengan instance createContext yang berbeda.

Ringkasan

  • useContext — hook untuk membaca nilai dari konteks React, menghilangkan kebutuhan props drilling.
  • createContext — membuat objek konteks dengan Provider untuk pengiriman data dan defaultValue untuk kasus tanpa Provider.
  • Memoisasi value — gunakan useMemo untuk value di Provider untuk menghindari render ulang konsumen yang tidak perlu.
  • Pemisahan konteks — bagi status global menjadi beberapa konteks kecil berdasarkan grup logis.
  • Hierarki Provider — Provider dari tipe yang sama dapat disarangkan untuk menimpa nilai di bagian pohon.
  • useContext + useReducer — pengganti ringan Redux untuk aplikasi menengah tanpa dependensi eksternal.
  • Tidak menggantikan Redux — untuk logika kompleks dengan middleware dan pembaruan sering, pilih Redux dengan selector.

Kami akan mengembangkan aplikasi seluler turnkey

IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.

Diskusikan proyek

Baca juga