Topik wawancara representatif

Wawancara Frontend: Bagaimana Cara Merancang Kartu Dashboard yang Merespons Ukuran Kontainer?

FrontendSulit
Tim Redaksi Offer.ccDipublikasikan Diperbarui

Pertanyaan

Sebuah kartu dashboard dapat diubah ukurannya melalui interaksi seret (drag) dan dapat berubah lebarnya saat sidebar diciutkan (collapse), font dimuat, atau grid mengalami reflow. Kartu ini harus beralih ke tata letak ringkas di bawah 320px sambil tetap responsif selama pengubahan ukuran secara kontinu. Rancang implementasinya, jelaskan mengapa window.resize tidak memadai, tunjukkan cara menghindari loop umpan balik ResizeObserver, dan jelaskan verifikasi performa serta kompatibilitasnya.

Konteks dan cakupan

Anda mengelola dashboard multi-kolom. Ukuran kartu ditentukan oleh grid, penyeretan, sidebar, dan pemuatan font, sehingga tidak dapat diperlakukan sebagai fungsi dari ukuran viewport semata. Di bawah 320px, kartu menampilkan judul ringkas dan metrik satu kolom; di atas ambang batas tersebut, kartu menampilkan tata letak penuh. Menciutkan sidebar tanpa mengubah ukuran jendela harus segera diterapkan.

Pertanyaan ini menguji pengukuran tingkat elemen, timing tata letak browser, siklus hidup React, dan batasan performa. Materi wawancara front-end publik umumnya mencakup DOM, CSS, event browser, dan performa; dokumentasi platform memberikan detail perilaku notifikasi dan loop ResizeObserver yang presisi untuk tindak lanjut yang lebih mendalam.

Apa yang sedang diuji oleh pewawancara

  • Menjelaskan bahwa window.resize menggambarkan perubahan viewport, bukan reflow grid, pergantian font, atau perubahan ukuran elemen induk.
  • Memilih content-box atau border-box dan mendefinisikan arti dari ambang batas tersebut.
  • Menuliskan hasil pengukuran ke state atau variabel CSS tanpa mengubah ukuran elemen yang diamati secara sinkron.
  • Menangani penggantian target, unmounting, node tersembunyi, browser lama, dan jumlah kartu yang banyak.
  • Membuktikan kelancaran dengan metrik pengguna, tugas panjang (long tasks), dan trace tata letak alih-alih hanya mengandalkan jumlah panggilan callback.

Pertanyaan klarifikasi di awal

  • Apakah ambang batas tersebut berkaitan dengan lebar content-box, lebar border-box, atau keputusan khusus gaya yang dapat diekspresikan oleh CSS container queries?
  • Apakah perubahan ukuran harus memicu pemrosesan data, atau hanya mengubah presentasi tampilan?
  • Haruskah UI mengikuti setiap frame, atau apakah satu pembaruan gabungan (coalesced) per frame sudah cukup?
  • Apa batas minimum dukungan browser, dan apakah rendering sisi server dapat menyentuh window?
  • Apakah ada puluhan atau ribuan kartu, dan bisakah hanya kartu yang terlihat yang diamati?

Jawaban 30 detik

“Pertama-tama saya akan menetapkan bahwa ini adalah masalah ukuran elemen, bukan masalah ukuran viewport. Untuk breakpoint khusus gaya, saya lebih memilih CSS container queries. Jika JavaScript memerlukan hasil pengukuran, saya akan memasang ResizeObserver di sisi klien, membaca box yang telah ditentukan, mendeduplikasi state ambang batas, dan menulis variabel CSS atau state diskrit. Callback tidak boleh mengubah ukuran yang diamati secara sinkron; penulisan yang tidak esensial dapat dijadwalkan untuk frame berikutnya, dan cleanup harus memutuskan sambungan (disconnect) observer. Untuk kartu dalam jumlah banyak, saya akan membatasi set yang diamati serta mengukur INP, long tasks, dan biaya tata letak. Browser lama mendapatkan fallback eksplisit berupa tata letak tetap, container queries, atau listener viewport yang di-throttle.”

Jawaban mendalam

Langkah 1: Periksa apakah CSS sudah cukup

Jika persyaratannya hanya “menampilkan gaya ringkas di bawah 320px,” container query biasanya lebih sederhana dan menjaga pengukuran tetap berada di luar JavaScript. ResizeObserver dapat dibenarkan ketika ukuran mendorong sampling grafik, virtualisasi, renderer pihak ketiga, atau logika bisnis yang dapat diamati.

Langkah 2: Tentukan kontrak ukuran

ResizeObserverEntry mengekspos pengukuran content box dan border box. Tentukan box mana yang memegang ambang batas, lalu standarisasi unit dan pembulatan. Sampel floating-point tidak otomatis menjadi event bisnis; deduplikasi transisi 319.9 ke 320.1 sebagai state breakpoint jika memang itu kontrak produknya.

Langkah 3: Tetapkan siklus hidup observer

Buat observer setelah komponen klien terpasang (mount), amati node kartu, dan panggil unobserve atau disconnect saat node berubah atau komponen di-unmount. Di React, biarkan ref memegang target dan Effect memegang pembuatan serta pembersihan observer sehingga rendering biasa tidak membuatnya kembali.

tsx
const ref = useRef<HTMLDivElement>(null)
const [compact, setCompact] = useState(false)

useEffect(() => {
  const node = ref.current
  if (!node || !('ResizeObserver' in window)) return

  const observer = new ResizeObserver(([entry]) => {
    const width = entry.contentRect.width
    const next = width < 320
    setCompact((current) => (current === next ? current : next))
  })

  observer.observe(node)
  return () => observer.disconnect()
}, [])

Langkah 4: Mencegah loop umpan balik callback

Jika callback mengubah lebar atau tinggi elemen yang diamati, perubahan tersebut dapat menjadwalkan notifikasi lain dan pada akhirnya menghasilkan ResizeObserver loop completed with undelivered notifications. Jaga agar callback tetap fokus pada kontrak ukuran, atau jadwalkan penulisan visual dengan requestAnimationFrame dan buat menjadi idempoten.

Langkah 5: Pisahkan pengukuran dari rendering

Tuliskan pengukuran ke CSS custom property jika CSS dapat menangani tata letak, atau simpan hanya state diskrit seperti compact. Jangan memasukkan setiap perubahan piksel ke dalam state React selama operasi seret. Jika nilai kontinu diperlukan, gabungkan (coalesce) notifikasi per frame animasi dan catat frame yang terlewat serta long tasks.

Langkah 6: Tangani banyak kartu dan node tersembunyi

Untuk ribuan kartu, amati hanya node yang terlihat atau biarkan lapisan tata letak mendistribusikan pengukuran. display: none, panel yang diciutkan, dan virtualisasi mengubah ukuran yang dapat diamati; setelah node menjadi terlihat, verifikasi bahwa notifikasi pertama memulihkan state yang benar. Observer bukanlah loop polling.

Langkah 7: Tentukan batas fallback dan server

Rendering server tidak dapat mengakses window. Deteksi dukungan di dalam Effect klien. Tanpa ResizeObserver, gunakan tata letak tetap, aturan CSS media/container, atau listener viewport yang di-throttle, dan dokumentasikan perilaku tingkat elemen yang tidak dapat disediakan oleh fallback tersebut.

Langkah 8: Verifikasi dengan bukti

Uji penciutan sidebar, penyeretan, pemuatan font, reflow grid, rotasi, dan zoom browser. Rekam callback, tata letak, paint, dan long tasks di Chrome Performance; gunakan INP atau latensi input (input delay) untuk memeriksa responsivitas saat menyeret. Tambahkan pengujian untuk peringatan loop konsol dan verifikasi bahwa kartu yang telah di-unmount tidak lagi menerima pembaruan.

Pertimbangan kompromi dan batasan

Container queries vs ResizeObserver

Container queries cocok untuk breakpoint khusus gaya dan tetap bersifat deklaratif. ResizeObserver cocok untuk kalkulasi JavaScript dan rendering pihak ketiga tetapi memerlukan kontrol siklus hidup dan performa. Batasannya adalah apakah hasil pengukuran harus keluar dari lapisan gaya.

content-box vs border-box

Gunakan content-box untuk ambang batas tata letak konten dan border-box untuk kontrak kartu luar yang mencakup padding dan border. Pilihan yang salah akan menggeser breakpoint; cantumkan pilihan tersebut dalam kontrak dan pengujian.

Nilai kontinu vs diskrit

Lebar kontinu dapat menggerakkan grafik tetapi sering diperbarui. Breakpoint diskrit lebih stabil dan lebih mudah diuji. Mulailah dengan kontrak diskrit dan tambahkan pembaruan kontinu hanya dengan anggaran performa yang terukur dan manfaat visual yang jelas.

Latihan penanganan kegagalan dan evolusi

Kegagalan: hanya mendengarkan window.resize

Penciutan sidebar dan reflow grid tidak mengubah viewport, sehingga kartu tetap berada dalam tata letak yang salah. Amati kartu atau kontainernya dan uji perubahan non-viewport.

Kegagalan: memutasi ukuran yang diamati di dalam callback

Mutasi memicu callback lain dan dapat menciptakan loop serta tata letak ekstra. Tulis variabel CSS independen, gunakan state diskrit, atau jadwalkan pembaruan frame berikutnya yang idempoten.

Kegagalan: setState untuk setiap piksel

Operasi seret menciptakan frekuensi render React yang tinggi dan memperburuk respons input. Deduplikasi ambang batas, gabungkan dengan rAF, amati kartu yang terlihat saja, dan konfirmasikan biayanya di panel Performance.

Kesalahan umum dan tindak lanjut

Kesalahan: memperlakukan ResizeObserver sebagai event resize yang lebih kuat

API ini mengamati box elemen dan mengirimkan notifikasi sesuai dengan timing tata letak; ini bukan sekadar pengganti event viewport biasa.

Tindak lanjut: bagaimana Anda memverifikasi React Strict Mode?

Pastikan inisialisasi dan pembersihan pada masa pengembangan tetap berpasangan dan jumlah observer tidak menumpuk. Jangan salah mengira pemeriksaan pengembangan ekstra sebagai langganan ganda di produksi.

Tindak lanjut: bisakah callback memanggil getBoundingClientRect?

Bisa, tetapi pengukuran tambahan dapat menambah biaya tata letak. Lebih baik utamakan nilai box dari entri (entry) dan buktikan setiap pembacaan tambahan dengan trace performa.

Tindak lanjut: bagaimana cara menguji loop ukuran?

Buat callback mengubah gaya yang memengaruhi ukurannya sendiri, amati peringatan, jumlah notifikasi, dan ukuran akhir, lalu pastikan versi yang diperbaiki stabil tanpa notifikasi terus-menerus.

Tindak lanjut: kapan JavaScript tidak diperlukan?

Ketika persyaratannya hanya perubahan gaya breakpoint kontainer, pilih CSS container queries. Simpan JavaScript untuk data, pengukuran, atau rendering pihak ketiga yang benar-benar membutuhkannya.

Tindak lanjut: bagaimana Anda membuktikan bahwa pengoptimalan berhasil?

Bandingkan INP, jumlah long task, waktu tata letak, commit React, dan memori di bawah skrip seret yang sama. Jumlah callback saja bukanlah metrik pengalaman pengguna.

Sumber publik

Pertanyaan terkait