Ini adalah pertanyaan interview React yang paling sering muncul, dikelompokkan berdasarkan level dan dijawab seperti yang diharapkan pewawancara: singkat, benar untuk React 19, dan disertai alasan di balik aturannya. Di tempat yang lebih mudah dipahami dengan melihat perilakunya langsung, jawabannya punya editor live, dan beberapa pertanyaan memintamu menebak output konsol sebelum menjalankannya.
Sebelum mengklik: apa yang dicetak konsol di bawah pratinjau, dan apa yang ditampilkan tombolnya? Jawabannya ada di bagian pemula di bawah.
Pertanyaan tingkat pemula
Apa itu React?
React adalah library JavaScript untuk membangun antarmuka pengguna dari komponen. Kamu menulis fungsi yang mengembalikan deskripsi UI untuk data saat ini, dan saat data itu berubah, React mencari tahu apa yang berubah lalu memperbarui DOM untukmu. React hanya menangani lapisan tampilan: routing, fetch data, dan form berasal dari library lain atau dari framework seperti Next.js.
Apa itu JSX?
JSX adalah ekstensi sintaks yang memungkinkanmu menulis markup di dalam JavaScript. Compiler (Babel, esbuild, SWC) mengubah setiap tag menjadi pemanggilan yang membuat elemen React, jadi <p className="note">{text}</p> menjadi objek dengan type: 'p' beserta props-nya. Karena ini JavaScript, kamu memakai className, bukan class, menaruh ekspresi di dalam {}, dan setiap tag harus ditutup. Halaman JSX membahas aturannya secara rinci.
Apa perbedaan komponen dan elemen?
Komponen adalah fungsi (atau class) yang menerima props dan mengembalikan UI. Elemen adalah objek biasa yang dihasilkan JSX, yang mendeskripsikan apa yang harus dirender: <Avatar size={40} /> adalah elemen yang type-nya adalah fungsi Avatar. React memanggil komponenmu untuk mengubah elemen menjadi elemen-elemen lain, terus sampai ke tag DOM. Elemen itu murah dan immutable; kamu tidak pernah memanggil komponen sendiri.
Apa perbedaan props dan state?
Props dikirim oleh induk dan bersifat read only di dalam komponen. State dimiliki komponen, berubah seiring waktu lewat setter, dan setiap perubahan menjadwalkan render baru. Cara umum untuk mengatakannya: props mengatur komponen, state adalah ingatannya. Nilai yang sama bisa menjadi state di induk dan prop di komponen anaknya.
Apa yang dicatat contoh pertama di halaman ini?
Contoh itu mencatat logged: 0, dan tombolnya menampilkan Count: 1, bukan 2. State adalah snapshot: count adalah konstanta selama satu render penuh, jadi kedua pemanggilan setCount(count + 1) menghitung 0 + 1, dan log-nya membaca nilai lama karena nilai baru baru ada di render berikutnya. Untuk menambah dua, pakai bentuk updater: setCount((c) => c + 1) dua kali.
Kenapa list butuh key, dan kenapa index adalah key yang buruk?
React memakai key untuk mencocokkan setiap item list dengan item dari render sebelumnya. Jika kamu memakai index array lalu menyisipkan item di paling atas, setiap index bergeser, jadi React menyimpan state setiap baris di posisi lamanya dan menempelkannya ke data yang salah.
Centang Ada, lalu klik "Add to top": centangnya melompat ke baris pertama yang baru. Ganti key={index} menjadi key={person.id} lalu coba lagi, dan centangnya tetap bersama Ada. Saat development, React juga memberi peringatan saat key tidak ada; pratinjau berjalan seperti build production, jadi kamu tidak akan melihat peringatan itu di sini.
Apa itu input terkontrol?
Input yang nilainya berasal dari state React: kamu mengirim value dan memperbarui state di onChange, jadi React menjadi satu-satunya sumber kebenaran dan kamu bisa memvalidasi atau mengubah setiap ketukan tombol. Input tidak terkontrol menyimpan nilainya sendiri di DOM, dan kamu membacanya saat dibutuhkan, lewat ref atau FormData milik form. Input terkontrol adalah pilihan default saat UI merespons apa yang diketik pengguna.
Apa arti lifting state up?
Saat dua komponen butuh data yang sama, kamu memindahkan state ke induk bersama terdekatnya dan mengirimnya ke bawah sebagai props, bersama fungsi untuk mengubahnya. Komponen anak berhenti menyimpan salinannya sendiri, jadi keduanya tidak akan pernah berselisih. Ini jawaban standar untuk "bagaimana komponen sibling berbagi state" sebelum beralih ke context atau store.
Apa saja aturan hook?
Panggil hook hanya di level teratas komponen atau custom hook, jangan pernah di dalam kondisi, loop, atau fungsi bersarang, dan hanya dari fungsi React, bukan dari fungsi JavaScript biasa. React mengidentifikasi setiap hook berdasarkan urutan pemanggilannya, jadi urutan itu harus sama persis di setiap render. Package eslint-plugin-react-hooks menegakkan kedua aturan ini.
Apa itu fragment?
Fragment mengelompokkan beberapa elemen tanpa menambah node DOM: <>...</>, atau <Fragment key={id}> saat kamu butuh key di dalam list. Sebuah komponen harus mengembalikan satu root, dan fragment memungkinkan root itu berupa beberapa sibling, yang penting di dalam tabel dan layout flex, di mana div tambahan akan merusak markup-nya.
Pertanyaan tingkat menengah
Bagaimana cara kerja array dependensi useEffect?
React menjalankan effect setelah commit hasil render (biasanya setelah browser menggambar), lalu menjalankannya lagi setelah render berikutnya yang mengubah salah satu nilai di array (dibandingkan dengan Object.is). Tanpa array, effect berjalan setelah setiap render; dengan [], effect berjalan sekali setelah render pertama. Setiap nilai dari komponen yang dibaca effect harus ada di array, dan linter memberi tahu saat ada yang terlewat.
Kapan cleanup effect berjalan?
Fungsi yang kamu kembalikan dari effect berjalan sebelum effect berjalan lagi dengan dependensi baru, dan sekali saat komponen unmount. Di situlah kamu membatalkan apa yang disiapkan effect: menghapus timer, menghapus listener, menutup koneksi.
Klik "Switch room" dan perhatikan konsol: cleanup untuk room lama berjalan lebih dulu, lalu effect terhubung ke room yang baru. "Hide chat" hanya menjalankan cleanup. Saat development, StrictMode menambahkan satu siklus connect, disconnect, connect tambahan saat mount untuk memeriksa apakah cleanup-mu berfungsi; pratinjau berjalan seperti build production, jadi kamu hanya melihat urutan yang sebenarnya.
Kenapa state saya terlihat usang di dalam setInterval?
Callback interval adalah closure atas count dari render yang membuatnya. Dengan array dependensi kosong, effect tidak pernah berjalan lagi, jadi callback itu terus membaca count pertama selamanya.
broken mencapai 1 lalu berhenti, karena setiap tick menghitung 0 + 1. fixed terus menghitung, karena fungsi updater menerima nilai terbaru. Menambahkan broken ke array dependensi juga berhasil, dengan biaya interval-nya dihapus dan dibuat ulang setiap detik.
Apa itu batching?
React mengelompokkan beberapa update state menjadi satu render. Sejak React 18, ini berlaku di mana saja: event handler, timeout, promise, dan listener event bawaan. Jika kamu butuh DOM diperbarui segera setelah satu update, flushSync dari react-dom bisa menonaktifkannya, tetapi jarang dibutuhkan.
Klik itu mencatat satu render 1 1 1, bukan tiga render. Tiga update state di dalam timeout dulu berarti tiga render sebelum React 18.
Apa yang dicatat kode ini? (urutan effect)
Baca kodenya lalu tuliskan empat baris yang akan dicetak konsol, secara berurutan, sebelum kamu melihatnya.
Render berjalan dari atas ke bawah: render App, lalu render Child. Effect berjalan dari bawah ke atas, setelah commit seluruh tree selesai: effect Child, lalu effect App. Effect milik induk bisa mengandalkan bahwa effect anak-anaknya sudah berjalan.
Apa perbedaan useMemo dan useCallback?
useMemo(() => compute(a, b), [a, b]) menyimpan hasil sebuah perhitungan. useCallback(fn, [deps]) menyimpan fungsinya itu sendiri, jadi sama dengan useMemo(() => fn, [deps]). Keduanya hanya membantu saat ada sesuatu di hilir yang membandingkan berdasarkan referensi: child yang memakai memo, atau array dependensi milik hook lain. Sejak React Compiler 1.0 (Oktober 2025), sebuah langkah build bisa menambahkan memoization ini secara otomatis, tetapi memoization manual tetap berjalan dan masih akan kamu lihat di sebagian besar codebase.
Apa fungsi React.memo, dan kenapa sering butuh useCallback?
memo(Component) melewatkan render ulang komponen saat props-nya sama dengan sebelumnya, dibandingkan satu per satu dengan Object.is. Fungsi yang ditulis inline di induk adalah fungsi baru di setiap render, jadi dihitung sebagai prop yang berubah dan menggagalkan memo. useCallback mempertahankan fungsi yang sama di antara render.
Bersihkan konsol lalu klik "Re-render parent": hanya render inline handler yang muncul. Child yang lain mendapat fungsi yang sama dan dilewati. Hapus memo(...) di sekitar Button, dan keduanya mencatat log di setiap klik, yang menunjukkan bahwa useCallback saja tidak melakukan apa pun.
Apa itu context, dan apa biayanya?
Context mengirim sebuah nilai ke setiap komponen di bawah provider tanpa menyalurkannya lewat props: createContext, lalu <ThemeContext value={theme}> di React 19 (atau <ThemeContext.Provider>), dan useContext(ThemeContext) untuk membacanya. Biayanya, setiap komponen yang membaca context ikut dirender ulang saat nilainya berubah, dan memo tidak menghentikannya. Jaga agar tetap ringan dengan memecah nilai-nilai yang tidak berkaitan ke context terpisah, membungkus nilai berupa objek dengan useMemo, dan menjauhkan state yang cepat berubah dari context tingkat aplikasi. Lihat useContext.
Apa itu ref, dan kapan memakainya alih-alih state?
useRef(initial) mengembalikan objek yang property current-nya bertahan di antara render, dan mengubahnya tidak memicu render. Pakai ref untuk nilai yang tidak memengaruhi tampilan layar (id timer, nilai sebelumnya, sebuah flag) dan untuk akses DOM (<input ref={inputRef}> lalu inputRef.current.focus()). Jika nilainya ditampilkan di layar, tempatnya di state.
Apa itu virtual DOM, dan apa itu reconciliation?
Di setiap render, React membuat tree elemen baru dan membandingkannya dengan yang sebelumnya; perbandingan inilah yang disebut reconciliation. Jika type sebuah elemen berubah (div menjadi section, atau ProfileA menjadi ProfileB), React menghancurkan subtree itu beserta state-nya lalu membuat yang baru. Jika type-nya sama, React mempertahankan node DOM-nya dan memperbarui props yang berubah, dan memakai key untuk mencocokkan anak-anak di dalam list. "Virtual DOM" adalah sebutan populer untuk tree di memori itu; kecepatannya berasal dari hanya menyentuh yang berubah, bukan dari tree itu sendiri yang cepat.
Apa itu custom hook?
Custom hook adalah fungsi yang namanya diawali use dan memanggil hook lain, sehingga kamu bisa memakai ulang logika yang punya state antarkomponen: useOnlineStatus, useLocalStorage, useDebouncedValue. Setiap komponen yang memanggilnya mendapat state sendiri yang terpisah; custom hook berbagi logika, bukan data. Lihat custom hook.
Apa fungsi StrictMode?
<StrictMode> menyalakan pemeriksaan tambahan hanya saat development. StrictMode merender komponen dua kali untuk memunculkan render yang tidak murni, menjalankan setup, cleanup, setup effect sekali saat mount untuk memunculkan cleanup yang terlewat, melakukan hal yang sama untuk ref callback, dan memberi peringatan tentang API yang deprecated. Semua ini tidak terjadi di build production, jadi log konsol ganda saat development itu wajar dan bukan bug.
Pertanyaan tingkat lanjutan
Apa yang dicatat kode ini? (render, layout effect, effect)
Satu tebakan lagi. Tiga log, tiga momen berbeda dalam sebuah render.
Urutannya adalah render, lalu useLayoutEffect, lalu useEffect, meskipun useEffect ditulis lebih dulu. Layout effect berjalan setelah React memperbarui DOM tetapi sebelum browser menggambar, itulah sebabnya cocok untuk mengukur sebuah elemen; effect biasa berjalan belakangan, biasanya setelah browser menggambar, dan sebaiknya menjadi pilihan default.
Apa itu error boundary?
Class component yang menangkap error yang dilempar saat merender anak-anaknya dan menampilkan fallback alih-alih membuat seluruh aplikasi unmount. Error boundary butuh static getDerivedStateFromError (untuk beralih ke fallback) dan biasanya componentDidCatch (untuk mencatat log). Masih belum ada padanan hook-nya, jadi di codebase yang memakai function component, tim menulis satu class atau memakai package react-error-boundary.
Klik "Break it": fallback hanya menggantikan anak-anak boundary, tombolnya tetap ada, dan React tetap melaporkan error yang tertangkap di konsol. Boundary tidak menangkap error di event handler, di kode async seperti setTimeout, atau di boundary itu sendiri. Untuk itu, kamu memakai try/catch dan mengatur state.
Apa itu portal?
createPortal(children, domNode) dari react-dom merender anak-anaknya ke node DOM lain, biasanya document.body, sambil mempertahankannya di posisi yang sama di tree React. Modal, tooltip, dan toast memakainya untuk lolos dari overflow: hidden atau stacking context milik induk. Context tetap berfungsi melewati portal, dan event mengalami bubbling lewat tree React, jadi klik di dalam portal sampai ke onClick milik induk meskipun node DOM-nya berada di tempat lain. Lihat portal.
Apa itu Suspense dan lazy?
lazy(() => import('./Chart')) memuat kode sebuah komponen saat pertama kali dirender, yang memecah bundle-mu. <Suspense fallback={<Spinner />}> menampilkan fallback selama ada sesuatu di dalamnya yang masih dimuat: kode lazy, atau data yang dibaca dengan use(promise) atau framework yang mendukung Suspense. Penempatan boundary menentukan bagian halaman mana yang menunggu bersama-sama.
import { lazy, Suspense } from 'react';
const Chart = lazy(() => import('./Chart.jsx'));
export default function Dashboard() {
return (
<Suspense fallback={<p>Loading chart...</p>}>
<Chart />
</Suspense>
);
}
Apa fungsi useTransition?
useTransition menandai update state sebagai tidak mendesak. const [isPending, startTransition] = useTransition() dan startTransition(() => setTab('posts')) memungkinkan React menjaga layar saat ini tetap responsif dan menyela render yang lambat jika datang update yang lebih mendesak, seperti ketukan tombol. isPending memberi tahu kapan perlu menampilkan petunjuk. Di React 19, fungsi yang kamu kirim boleh async, dan itulah yang disebut React sebagai action. Jangan pakai untuk memperbarui nilai input teks itu sendiri; update itu harus mendesak.
Apa itu React Server Components?
Komponen yang hanya berjalan di server (atau saat build) dan mengirim hasil render-nya ke browser, tidak pernah kodenya. Komponen ini bisa async dan langsung membaca database atau file system, tetapi tidak bisa memakai state, effect, atau API browser. File yang ditandai 'use client' memulai batas client tempat komponen interaktif berada, dan 'use server' menandai server function yang bisa dipanggil kode client. Kamu memakainya lewat framework seperti Next.js dengan App Router; aplikasi Vite biasa tidak punya server untuk menjalankannya.
Apa yang berubah di React 19?
- Actions: fungsi async di dalam transition, dengan keadaan pending yang diurus untukmu.
<form action={fn}>memanggilfndenganFormDatamilik form. - Hook baru:
useActionStateuntuk hasil dan keadaan pending sebuah form,useOptimisticuntuk UI optimis, danuseFormStatusdireact-dom. use: membaca promise (melakukan suspend sampai promise selesai) atau context, dan berbeda dengan hook lain, bisa dipanggil di dalam kondisi.refsebagai prop: function component menerimarefseperti prop lain, jadiforwardReftidak lagi dibutuhkan untuk kode baru. Ref callback bisa mengembalikan fungsi cleanup.<Context>sebagai provider, ditambah tag<title>dan<meta>yang dipindahkan ke head dokumen.- Yang dihapus:
ReactDOM.render, string ref, context lawas, dandefaultPropspada function component (pakai nilai default parameter).
// React 19: ref is a normal prop
function TextInput({ ref, ...props }) {
return <input ref={ref} {...props} />;
}
Halaman React 19 punya contoh yang bisa dijalankan untuk masing-masing.
Bagaimana cara menguji komponen React?
Dengan React Testing Library dan test runner seperti Vitest atau Jest. Kamu merender komponennya, mencari elemen seperti yang dilakukan pengguna (berdasarkan role, label, atau teks), berinteraksi dengan user-event, lalu memeriksa apa yang terlihat, bukan state internalnya. Dengan begitu, test tetap valid meskipun kodenya mengalami refactor.
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import Counter from './Counter';
test('counts clicks', async () => {
const user = userEvent.setup();
render(<Counter />);
await user.click(screen.getByRole('button', { name: /clicked 0 times/i }));
expect(screen.getByRole('button')).toHaveTextContent('Clicked 1 times');
});
toHaveTextContent berasal dari @testing-library/jest-dom. Untuk alur lengkap yang melintasi beberapa halaman, tim menambahkan Playwright atau Cypress di atasnya.
Bagaimana cara menemukan dan memperbaiki masalah performa?
Ukur dulu. Buka tab Profiler di React DevTools, rekam interaksi yang lambat, lalu baca flame chart-nya: chart itu menunjukkan komponen mana yang dirender, berapa lama masing-masing, dan (dengan pengaturan "record why each component rendered") alasannya. Perbaikan yang umum, sesuai urutan untuk dicoba: pindahkan state ke bawah agar lebih sedikit komponen yang bergantung padanya, kirim subtree yang lambat sebagai children, lakukan memoization pada bagian yang berat dengan memo, useMemo, dan useCallback, virtualisasi list yang panjang, dan tunda update yang berat dengan useTransition atau useDeferredValue. Lakukan profiling di build production atau build profiling; build development lebih lambat dan membesar-besarkan waktu render.
Kenapa sebuah komponen harus murni?
Dengan props, state, dan context yang sama, sebuah komponen harus mengembalikan JSX yang sama dan tidak mengubah apa pun di luar dirinya selama render. React bisa merender sebuah komponen lebih dari sekali, tidak berurutan, atau membuang hasil render (transition, Suspense, StrictMode), jadi side effect di isi komponen, seperti mengubah variabel atau mengirim request, berjalan dalam jumlah yang tidak bisa diprediksi. Side effect tempatnya pertama-tama di event handler, dan di effect saat tidak ada event yang memicunya.
Kapan sebaiknya tidak memakai effect?
Saat nilainya bisa dihitung selama render (list hasil filter, nama lengkap, total), saat pekerjaannya dipicu oleh aksi pengguna (taruh di event handler), dan saat kamu ingin mengatur ulang state ketika sebuah prop berubah (pakai key). Effect dipakai untuk sinkronisasi dengan sesuatu di luar React: koneksi jaringan, API browser, widget pihak ketiga. Rangkaian effect yang mengatur state adalah sumber umum render tambahan dan bug.
Pertanyaan yang sering diajukan
Apa itu React?
React adalah library JavaScript untuk membangun antarmuka pengguna dari komponen. Kamu mendeskripsikan seperti apa tampilan layar untuk data saat ini, dan React memperbarui DOM yang sesungguhnya saat data itu berubah.
Apa perbedaan state dan props?
Props adalah input yang dikirim induk ke sebuah komponen, dan komponen itu memperlakukannya sebagai read only. State adalah data milik komponen yang berubah seiring waktu lewat setter, yang membuat React merendernya lagi.
Apa itu hook di React?
Hook adalah fungsi yang namanya diawali use, yang memungkinkan function component memakai fitur React: useState untuk state, useEffect untuk side effect, useContext untuk context, useRef untuk nilai yang tidak memicu render, dan lainnya.
Apa itu virtual DOM?
Virtual DOM adalah sebutan untuk deskripsi UI milik React yang disimpan di memori. Di setiap render, React membuat deskripsi baru, membandingkannya dengan yang sebelumnya, dan hanya menerapkan perbedaannya ke DOM yang sesungguhnya. Perbandingan itu disebut reconciliation.
Kenapa key penting di list React?
Key memberi tahu React item mana adalah item yang mana di antara render. Dengan key yang stabil (seperti id), React menjaga state dan node DOM setiap item tetap melekat pada data yang benar saat item ditambahkan, dihapus, atau diurutkan ulang. Memakai index array merusak hal ini saat urutannya berubah.
Apa itu JSX?
JSX adalah ekstensi sintaks yang memungkinkanmu menulis markup mirip HTML di JavaScript. Compiler mengubah setiap tag menjadi pemanggilan fungsi yang membuat elemen React, jadi <h1>Hi</h1> menjadi objek biasa yang mendeskripsikan sebuah h1.