Perintah dan cakupan
Sebuah kartu dasbor mengubah tata letak berdasarkan kontainernya sendiri, bukan viewport. Implementasi awal membaca dan menulis gaya secara sinkron di dalam callback ResizeObserver, yang menyebabkan frame lambat dan sesekali terjadi galat loop. Rancang observasi, pengukuran, pembaruan, dan pembersihan. Keterampilan intinya adalah tata letak browser dan lifecycle komponen, jadi ini termasuk dalam frontend.
Apa yang dievaluasi pewawancara
Jawaban harus membedakan media query viewport dari observasi elemen serta mencakup timing callback, pilihan box, pemisahan baca/tulis, perlindungan loop, pembaruan batch, React Strict Mode, beberapa target, elemen tersembunyi, SSR, dan aksesibilitas.
Pertanyaan untuk diklarifikasi terlebih dahulu
- Apakah kita mengobservasi content box, border box, atau device-pixel content box?
- Apakah pembaruan mengubah class, variabel CSS, dimensi Canvas, atau geometri DOM?
- Apakah callback akan mengubah ukuran elemen yang diobservasi atau ukuran elemen leluhurnya?
- Berapa banyak target yang ada, dan apakah pembaruan harus digabungkan ke dalam frame berikutnya?
- Bagaimana pembuatan dan pembersihan observer ditangani saat unmount, status tersembunyi, dan SSR?
Kerangka jawaban 30 detik
“Buat satu observer stabil di sisi klien dan observasi box yang diperlukan. Di dalam callback, kumpulkan ukuran terlebih dahulu, lalu pisahkan pembacaan DOM dari penulisan. Terapkan class atau variabel CSS dalam frame yang dibatch sehingga perubahan tata letak tidak dapat langsung memberikan umpan balik ke target yang diobservasi. Abaikan nilai yang tidak berubah; saat unmount, hentikan pembaruan, lakukan unobserve, dan disconnect. Uji tugas panjang, jumlah tata letak, galat loop, dan remount pada Strict Mode.”
Solusi langkah demi langkah
ResizeObserver memantau content box atau border box suatu elemen, terlepas dari viewport. Pilih box secara sengaja: breakpoint tata letak biasanya menggunakan ukuran content atau border, sedangkan penggambaran yang akurat hingga tingkat piksel dapat menggunakan device-pixel content. Jangan membaca properti yang memaksakan tata letak secara berulang di dalam callback.
Pertama, kumpulkan ukuran terbaru setiap entri ke dalam set pending kecil, lalu hitung breakpoint secara bersamaan. Simpan pembacaan geometri dalam satu batch dan tulis variabel CSS atau class setelah kalkulasi. Jika penulisan dapat memengaruhi tata letak, jadwalkan dengan requestAnimationFrame dan bandingkan batch berikutnya dengan nilai sebelumnya.
Feedback loop adalah kondisi “observasi ukuran, tulis gaya, ubah ukuran lagi.” Misalnya, lebar mengubah padding dan padding mengubah lebar. Tambahkan histeresis, batasan kontainer tetap, atau perbarui properti yang tidak mengubah target yang diukur. Jika pengubahan ukuran diperlukan, batasi pekerjaan menjadi satu pembaruan per frame dan deteksi konvergensi. Browser dapat menunda notifikasi yang tidak konvergen dan melaporkan galat loop; mengabaikan galat bukanlah sebuah perbaikan.
Di React, buat observer dalam useLayoutEffect khusus klien atau effect yang sesuai, dengan ref dan callback yang stabil. Strict Mode dapat menjalankan setup dan pembersihan dua kali, sehingga pembersihan harus idempoten. Saat unmount, hentikan penerapan pembaruan, lakukan unobserve pada target, dan disconnect. SSR tidak boleh mengakses window atau membuat observer.
Untuk banyak kartu, gunakan observer bersama dan petakan entry.target ke state komponen, tetapi pertahankan kepemilikan yang jelas agar satu kartu tidak memblokir seluruh callback. Selama penyeretan (drag), pertahankan hanya ukuran terbaru dan gabungkan pembaruan dalam frame animasi daripada menambahkan debounce sembarangan yang membuat tata letak tertinggal.
Elemen tersembunyi, display:none, pemuatan font, dan scrollbar dapat mengubah ukuran. Berikan nilai default yang dapat digunakan untuk entri awal berukuran nol dan alihkan setelah pengukuran valid pertama. Utamakan CSS container query untuk breakpoint gaya murni; gunakan ResizeObserver saat JavaScript harus menggerakkan Canvas, widget pihak ketiga, atau kalkulasi bisnis.
Verifikasi dengan panel Performance saat menyeret, memuat font, menyembunyikan dan menampilkan kartu, memutar viewport, dan me-mount banyak instance. Pastikan bahwa setiap perubahan ukuran hanya menyebabkan pekerjaan yang diperlukan, tanpa loop persisten, observer duplikat, pembaruan pasca-unmount, atau layout thrash yang signifikan. Uji juga pengoperasian keyboard dan pembaca layar.
Contoh jawaban berkualitas tinggi
“Saya membuat ResizeObserver sisi klien yang stabil dan memilih content atau border box dengan sengaja. Callback mencatat entri terbaru dan menghitung breakpoint; ia tidak membaca dan menulis tata letak berulang kali. Saya menerapkan variabel CSS atau class dalam frame yang dibatch. Jika penulisan mengubah ukuran yang diobservasi, saya menambahkan histeresis, batasan, dan pemeriksaan konvergensi untuk mencegah feedback loop.
Pembersihan React bersifat idempoten: hentikan pembaruan saat unmount, unobserve, dan disconnect. Banyak kartu dapat berbagi satu observer dengan dispatch berbasis target. Saya menguji pengubahan ukuran saat drag, pemuatan font, status tersembunyi dan ditampilkan, serta remount Strict Mode, mengukur tata letak, tugas panjang, galat loop, langganan duplikat, dan interaksi yang dapat diakses.”
Kesalahan umum
- Memperlakukan ResizeObserver sebagai media query viewport → komponen gagal di berbagai kontainer → observasi elemen itu sendiri.
- Membaca dan menulis banyak DOM di dalam callback → tata letak paksa dan thrashing → batch pembacaan dan lakukan penulisan pada frame berikutnya.
- Mengubah target yang diobservasi tanpa konvergensi → feedback loop → gunakan histeresis, batasan, dan deteksi.
- Membuat observer pada setiap render → callback duplikat dan kebocoran memori → ref stabil, dependensi, dan pembersihan.
- Hanya melakukan unobserve tetapi mempertahankan state callback → pembaruan berlanjut setelah unmount → tandai tidak aktif, unobserve, dan disconnect.
- Menerapkan tata letak terbesar pada ukuran nol → paint pertama melompat secara visual → gunakan status default hingga entri valid ada.
- Menggunakan JavaScript untuk setiap breakpoint → kompleksitas yang tidak perlu → gunakan container query jika CSS sudah cukup.
- Hanya menguji penyeretan normal → masalah font, elemen tersembunyi, dan Strict Mode terlewat → cakup perubahan lifecycle dan sumber daya.
Pertanyaan lanjutan dan tanggapan
Pertanyaan lanjutan 1: Kapan callback berjalan?
Browser mengelompokkan (batch) notifikasi perubahan ukuran setelah tata letak. Perubahan yang tidak konvergen dapat ditunda dan memunculkan galat loop, sehingga callback tidak boleh menyebabkan perubahan tata letak yang tidak terbatas.
Pertanyaan lanjutan 2: Mengapa tidak menggunakan window.resize?
Itu mencerminkan perubahan viewport, bukan kartu yang berubah karena grid, sidebar, atau font. ResizeObserver mengobservasi elemen secara langsung.
Pertanyaan lanjutan 3: Bagaimana Anda memisahkan pembacaan dan penulisan?
Baca ukuran dari entri terlebih dahulu, hitung hasil, lalu batch penulisan variabel CSS atau class, menggunakan requestAnimationFrame bila diperlukan dan mengabaikan nilai yang tidak berubah.
Pertanyaan lanjutan 4: Satu observer per elemen atau observer bersama?
Beberapa elemen yang dimiliki secara independen dapat menggunakan observer terpisah. Banyak target dapat berbagi satu observer dan melakukan dispatch berdasarkan target, selama beban kerja callback tetap terbatas.
Pertanyaan lanjutan 5: Apa yang terjadi setelah display:none?
Perlakukan ukuran nol sebagai sementara, tunggu entri yang valid setelah ditampilkan, dan hindari penulisan loop saat tersembunyi. Jangan memperlakukan nol sebagai breakpoint permanen.
Pertanyaan lanjutan 6: Mengapa React Strict Mode mengungkap bug?
Mode pengembangan dapat menjalankan setup dan pembersihan effect dua kali untuk mengungkap efek samping yang asimetris. Pembersihan harus dapat diulang dan tidak meninggalkan observer atau callback pembaruan.
Pertanyaan lanjutan 7: Kapan CSS container query harus diutamakan?
Gunakan CSS untuk breakpoint kontainer murni. Gunakan ResizeObserver saat ukuran harus menggerakkan Canvas, API pihak ketiga, pengukuran kompleks, atau kalkulasi bisnis.