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 — 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.
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>;
}
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.
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.
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>
);
}
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.
// 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>
);
}
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.
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>
);
}
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.
| Kriteria | useContext | Redux |
|---|---|---|
| Kompleksitas | Tidak ada dependensi eksternal | Memerlukan konfigurasi store dan middleware |
| Render ulang | Semua konsumen pada setiap perubahan | Hanya yang berlangganan ke slice tertentu |
| DevTools | React DevTools | Redux DevTools dengan time-travel |
| Middleware | Tidak didukung | Redux Thunk, Saga, Observable |
| Kapan memilih | Aplikasi menengah, 3-5 konteks | Aplikasi 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 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.
// ❌ 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
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.
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.
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.
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”.
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
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.
Baca juga