Topik temu duga representatif

Temu Duga Frontend: Bagaimana Anda Menyahpepijat dan Membetulkan Ketakpadanan Hidratasi React?

FrontendSukar
Pasukan Editorial Offer.ccDiterbitkan Dikemas kini

Soalan

Halaman Next.js App Router melaporkan ralat React #418 untuk sebilangan kecil pengguna pengeluaran: masa, tema, atau ID borang kadangkala berbeza daripada HTML pelayan, butang kadangkala dicipta semula, dan persekitaran pembangunan tempatan tidak menghasilkan semula ralat tersebut dengan konsisten. Terangkan kontrak hidratasi, reka urutan diagnostik, betulkan rendering tidak deterministik, keadaan pelayar, HTML tidak sah, dan mutasi luaran, serta nyatakan bila useEffect, ssr: false, atau suppressHydrationWarning adalah wajar digunakan.

Masalah dan Konteks yang Berkaitan

Halaman produk Next.js App Router melakukan pramuat (prerender) HTML, kemudian memuatkan JavaScript dalam pelayar untuk menjadikan butang kegemaran dan borang stok-kembali interaktif. Pemantauan pengeluaran melaporkan ralat React #418 pada sebahagian kecil lawatan pertama. Pengguna yang terjejas mungkin melihat masa atau tema berkelip seketika (flash), label borang kehilangan kaitannya buat seketika, atau butang kegemaran dicipta semula. Pembangunan tempatan dan navigasi sisi klien yang berikutnya biasanya kelihatan normal.

Semakan mendapati empat operasi berisiko dalam laluan render Client Component yang sama: memformat masa dengan zon masa lalai pelayar, mencabang pada tema daripada localStorage, menjana ID borang dengan Math.random(), dan mengeluarkan teks kaya yang mungkin menghasilkan penyarangan tidak sah. Sebuah CDN berada di hadapan persekitaran pengeluaran, dan sesetengah pengguna mempunyai sambungan pelayar (browser extensions) yang mengubah halaman. Terangkan cara mengenal pasti peringkat yang menyebabkan snapshot pelayan berbeza daripada render klien pertama, tanpa menyahdayakan SSR untuk keseluruhan halaman atau menyekat amaran secara meluas.

Panduan temu duga frontend kanan KORE1 2026 secara langsung meminta calon menyahpepijat ketakpadanan hidratasi khusus pengeluaran yang tidak dapat dihasilkan semula secara tempatan. Bank soalan React MockIF 2026 juga menyenaraikan hidratasi sebagai soalan seni bina lanjutan. Dokumentasi React dan Next.js menetapkan kontrak output yang serupa dan mengenal pasti masa, nilai rawak, API pelayar, penyarangan tidak sah, dan mutasi DOM luaran sebagai puncanya. Oleh itu, soalan ini mempunyai perwakilan temu duga semasa yang boleh disahkan. Kemahiran terasnya ialah rendering pelayar dan penyahpepijatan hidratasi React, maka kategorinya ialah frontend. Soalan sedia ada mengenai gelung peristiwa (event loop), caching, prestasi, kunci (keys), dan penutupan basi (stale closures) tidak merangkumi kontrak ini.

Perkara yang Dinilai oleh Penemu Duga

Pertama, bolehkah calon mentakrifkan hidratasi dengan tepat? Pada pemuatan awal, pengguna melihat HTML yang dipramuat. Pelayar menghuraikannya, dan React melampirkan logik komponen serta pengendali peristiwa (event handlers) pada DOM sedia ada. Client Components masih boleh mengambil bahagian dalam pramuat HTML awal; "use client" tidak bermaksud rendering pelayar sahaja pada pemuatan pertama. Kontrak ini membandingkan hasil pelayan dengan render pertama klien, bukan dua render terkemudian yang rawak.

Kedua, bolehkah calon memisahkan empat kelas perbezaan menggunakan bukti? Input aplikasi mungkin berbeza, seperti snapshot data, masa semasa, atau nilai rawak. Persekitaran pelaksanaan mungkin berbeza melalui window, localStorage, bahasa, atau zon masa. Pelayar mungkin membaiki HTML yang tidak sah menjadi DOM yang berbeza. Akhir sekali, CDN, sambungan pelayar, atau skrip mungkin memutasi nod sebelum React bermula. Hanya melihat pada tindanan komponen (component stack) boleh terlepas proses penghuraian atau mutasi luaran yang berlaku lebih awal.

Ketiga, bolehkah calon memetakan setiap punca kepada pembaikan yang sesuai? Input yang stabil harus disiri dan diguna semula sebagai satu snapshot. Persekitaran pengguna boleh diselesaikan pada pelayan daripada kuki atau profil, atau dikemas kini dalam Effect selepas hidratasi. ID DOM rawak harus menggunakan useId. Penyarangan yang tidak sah harus diperbetulkan. SSR hanya perlu dinyahdayakan untuk komponen pihak ketiga yang kecil yang benar-benar tidak boleh dipramuat.

Akhir sekali, bolehkah calon membuktikan kecacatan itu telah hilang? Pelan yang kukuh merangkumi binaan pengeluaran, pemuatan awal sejuk (cold initial loads), JavaScript yang perlahan, gabungan locale dan zon masa, hit cache, pelayar bersih, dan pelayar yang terjejas oleh sambungan pelayar. Ia memeriksa ralat, identiti DOM, keadaan interaksi, dan kelipan visual. Konsol yang sunyi adalah satu hasil, bukan bukti lengkap.

Soalan Penjelasan Sebelum Menjawab

  • Adakah ralat berlaku hanya pada pemuatan dokumen awal, atau juga pada navigasi klien? Hidratasi ialah pengambilalihan pertama HTML sedia ada oleh React. Kecacatan pada navigasi terkemudian sebaliknya menunjukkan isu keadaan (state), caching, atau keadaan berlumba tak segerak (async race).
  • Adakah ketakpadanan berlaku pada teks, atribut, struktur nod, atau keseluruhan subpokok? Kekalkan ralat penuh, tindanan komponen, laluan, dan versi pelaksanaan dan bukannya meneka daripada nombor ralat pengeluaran yang terpotong.
  • Adakah pelayan mengetahui locale, zon masa, tema, dan kelompok eksperimen pengguna? Nilai yang tersedia melalui URL, kuki, atau profil harus ditetapkan pada pelayan dan dihantar ke klien. Nilai yang tidak diketahui memerlukan pemegang tempat (placeholder) yang stabil atau kemas kini pascahidratasi.
  • Adakah render klien pertama menggunakan snapshot data perniagaan yang tepat yang menjana HTML tersebut? Walaupun pelayar telah mengambil data yang lebih baharu sebelum hidratasi, paparan awal harus bermula daripada snapshot yang disiri dan disegarkan semula hanya selepas hidratasi.
  • Adakah HTML melalui CDN, proksi terjemahan, penyuntik keselamatan, atau pengoptimum? Tangkap kedua-dua respons asal dan pinggir untuk melihat sama ada perantara mengubah ruang putih, atribut, teg, atau urutan skrip.
  • Adakah ralat terhad kepada sambungan pelayar, pelayar mudah alih, atau wilayah tertentu? Perkara ini menentukan sama ada perlu membandingkan badan respons rangkaian dengan DOM sebenar serta-merta sebelum React bermula.
  • Adakah subpokok ini memerlukan pramuat? Kandungan yang bernilai untuk SEO, first paint, atau kebolehbacaan tanpa JavaScript harus mengekalkan SSR. Widget daun (leaf widget) pelayar sahaja mungkin mewajarkan ssr: false tempatan.
  • Apakah perubahan visual yang boleh diterima? Rendering dua fasa (two-pass rendering) boleh memelihara kontrak hidratasi tetapi mencipta perubahan yang kelihatan pada sambungan perlahan. Persetujui kandungan pemegang tempat, kestabilan reka letak, dan kebolehcapaian terlebih dahulu.

Rangka Kerja Jawapan 30 Saat

"Hidratasi memerlukan HTML pelayan dan render pertama klien menghasilkan struktur dan kandungan yang sama. Saya akan menangkap ralat, tindanan komponen, laluan, versi, locale, dan zon masa, kemudian menyelaraskan tiga bukti: HTML yang diterima melalui rangkaian, DOM yang dihuraikan oleh pelayar sebelum React mengambil alih, dan input kepada render klien pertama. Jika HTML rangkaian sudah berbeza, periksa snapshot data dan CDN. Jika ia berubah semasa penghuraian, periksa penyarangan tidak sah, sambungan pelayar, dan skrip awal. Jika ia mencapah apabila React merender, periksa masa, kerawakan, API pelayar, dan penyegaran data awal. Saya akan menggunakan semula satu snapshot yang disiri, menentukan locale dan timeZone, menggunakan useId, dan memperoleh keadaan pelayar daripada kuki atau selepas hidratasi dalam Effect. Saya akan mengkhususkan ssr: false untuk daun pelayar sahaja dan suppressHydrationWarning untuk perbezaan teks satu tahap yang tidak dapat dielakkan. Kemudian saya akan menjalankan pemuatan pengeluaran sejuk merentas matriks persekitaran dan mengesahkan tiada ralat boleh pulih, penggantian subpokok, kelipan, atau pepijat interaksi."

Perincian Langkah demi Langkah

Langkah 1: nyatakan tak varian (invariant) sebelum menyahpepijat komponen.

Katakan pokok komponen pelayan menghasilkan HTML daripada snapshot input S. Pelayar menghuraikan HTML menjadi DOM D, dan klien melakukan render pertamanya dengan input C. Hidratasi yang berjaya memerlukan D dan pokok klien sepadan bagi nod, teks, dan atribut yang disandarkan oleh React. Matlamatnya bukan sekadar untuk membuktikan bahawa kedua-dua persekitaran memuatkan fail sumber yang sama. Ia adalah untuk membuktikan bahawa S, penghuraian, dan C menghasilkan hasil yang sama.

React tidak menjamin bahawa setiap perbezaan atribut akan ditampal. Sesetengah ketakpadanan boleh dipulihkan dan menyebabkan subpokok dijana semula; dalam senario terburuk, pengendali boleh dilampirkan pada elemen yang salah. Oleh itu, ketakpadanan hidratasi bukanlah hingaran konsol yang tidak berbahaya.

Langkah 2: bina pakej bukti yang mewakili pemuatan pertama pengeluaran.

Rekodkan laluan, versi pelaksanaan, ID permintaan, status cache, locale, zon masa, sumber tema, kelompok eksperimen, User-Agent, dan tindanan komponen penuh tanpa mengumpul nilai sensitif. Gunakan binaan pengeluaran dan muat semula penuh (full reload). Hot reload, tingkah laku khusus pembangunan, dan navigasi klien tidak menghasilkan semula pemulaan sejuk (cold start) pengeluaran.

Bagi satu permintaan, kekalkan tiga artifak: badan respons yang dikembalikan oleh asal atau CDN, DOM yang dihuraikan dengan JavaScript dinyahdayakan, dan DOM serta-merta sebelum dan selepas ralat dengan JavaScript didayakan. Jika respons adalah betul tetapi pokok Elements sudah berbeza, periksa pembetulan penghurai HTML, sambungan pelayar, dan skrip pra-React terlebih dahulu. Jika DOM mencapah hanya apabila React bermula, bandingkan input render pertama.

Langkah 3: buang ketidakdeterministikan daripada laluan render.

Kod berikut membenarkan pelayan dan pelayar menggunakan persekitaran yang berbeza dan menjana ID baharu pada setiap render:

tsx
"use client"

export function StockNotice({ updatedAt }: { updatedAt: string }) {
  const isBrowser = typeof window !== "undefined"
  const theme = isBrowser ? localStorage.getItem("theme") ?? "light" : "light"
  const inputId = `stock-${Math.random()}`

  return (
    <section data-theme={theme}>
      <time dateTime={updatedAt}>{new Date(updatedAt).toLocaleString()}</time>
      <label htmlFor={inputId}>Back-in-stock alert</label>
      <input id={inputId} />
    </section>
  )
}

Lebih baik selesaikan nilai yang stabil pada pelayan dan hantar nilai tepat tersebut sebagai input awal Client Component. Jika locale, zon masa, dan tema tersedia dalam URL, kuki, atau profil, bacanya pada pelayan. Pemformatan tarikh harus menerima locale dan timeZone yang eksplisit. ID DOM harus menggunakan useId, dengan syarat pokok komponen pelayan dan klien itu sendiri kekal serupa:

tsx
"use client"

import { useId } from "react"

interface StockNoticeProps {
  updatedAt: string
  updatedLabel: string
  initialTheme: "light" | "dark"
}

export function StockNotice({
  updatedAt,
  updatedLabel,
  initialTheme,
}: StockNoticeProps) {
  const inputId = useId()

  return (
    <section data-theme={initialTheme}>
      <time dateTime={updatedAt}>{updatedLabel}</time>
      <label htmlFor={inputId}>Back-in-stock alert</label>
      <input id={inputId} />
    </section>
  )
}

Jika pelayan benar-benar tidak dapat mengetahui zon masa pelayar, render label UTC atau pemegang tempat tetap yang sama pada kedua-dua belah pihak, kemudian gantikannya dalam useEffect selepas hidratasi. Ini menambah satu render, jadi sediakan ruang dan nilai perubahan visual pada sambungan yang perlahan. Gunakan peraturan yang sama untuk data perniagaan: siri snapshot yang menjana HTML, gunakannya untuk render klien pertama, dan biarkan penyegaran latar belakang mengemas kini paparan hanya selepas hidratasi.

Langkah 4: periksa penghuraian pelayar dan mutasi luaran.

Pelayar membaiki HTML yang tidak sah secara toleran (permissively). Elemen blok di dalam perenggan atau butang di dalam butang lain boleh menghasilkan DOM yang dihuraikan yang tidak sama dengan struktur yang dikeluarkan oleh React. Betulkan semantik dan penyarangan, kemudian sahkan dengan pengesahan HTML dan pemeriksaan DOM. Effect bukanlah pembaikan untuk struktur yang tidak sah.

Jika kegagalan berlaku hanya pada hit cache pinggir, bandingkan respons asal dan pinggir serta nyahdayakan transformasi yang menulis semula HTML. Jika ia berlaku hanya dengan sambungan pelayar, hasilkan semula dalam profil bersih dan kenal pasti perkara yang diubah oleh sambungan tersebut sebelum React. Aplikasi boleh mengukur kesan tersebut, tetapi ia tidak seharusnya menyembunyikan semua ketakpadanan aplikasi sebenar hanya kerana sambungan pelayar yang tidak terkawal wujud. Pisahkan (bisect) skrip pihak ketiga dengan cara yang sama: alih keluar skrip tersebut daripada laluan awal satu demi satu dan kenal pasti penulisan DOM yang pertama.

Langkah 5: pilih laluan keluar kecemasan (escape hatches) mengikut kos.

useEffect adalah sesuai untuk data persekitaran yang hanya boleh dibaca selepas hidratasi, tetapi ia mencipta render kedua. dynamic dengan ssr: false sesuai untuk komponen pihak ketiga tempatan yang tidak boleh dilaksanakan pada pelayan dan tidak membawa kandungan SEO atau awal yang penting. Menukar keseluruhan halaman kepada rendering klien sahaja mengorbankan pramuat dan memanjangkan tempoh skrin kosong. suppressHydrationWarning hanya berfungsi sebagai laluan keluar cetek, dan React tidak menampal teks yang disekat. Ia adalah untuk perbezaan terpencil yang tidak dapat dielakkan, bukan pembaikan untuk zon masa, ID rawak, tema, atau data basi.

Langkah 6: buktikan pembaikan dengan matriks kegagalan.

Liputi sekurang-kurangnya dua locale, dua zon masa, tema cerah dan gelap, keadaan log masuk dan tanpa nama, hit dan miss cache, JavaScript normal dan tertunda, profil bersih, dan sambungan pelayar yang diketahui. Lakukan muat semula penuh untuk setiap kes. Pastikan tiada ralat hidratasi boleh pulih berlaku, subpokok penting tidak diganti, tingkah laku fokus dan peristiwa kekal betul, masa dan tema dikemas kini pada titik yang dimaksudkan, dan reka letak tidak melompat secara visual.

Tambah semakan kod untuk Date.now, Math.random, toLocaleString tersirat, window atau localStorage dalam render, penyarangan berbahaya, dan suppressHydrationWarning yang meluas. Ini menghalang insiden yang telah dibetulkan daripada berulang melalui kelas kesilapan yang sama.

Contoh Jawapan Berkualiti Tinggi

"Saya akan terlebih dahulu mengehadkan insiden kepada pemuatan dokumen awal. Next.js boleh mempramuat Client Components pada permintaan awal. Selepas pelayar menerima HTML, React mesti menghasilkan pokok yang sama daripada input awal yang sama sebelum melampirkan pengendali. Komponen ini membaca localStorage, menggunakan zon masa lalai pelayar, dan mencipta ID rawak semasa render, jadi ketiga-tiga nilai boleh berbeza daripada pelayan. Struktur teks kaya juga mungkin dibaiki oleh pelayar sebelum React melihatnya.

Saya akan mengambil satu peristiwa sebenar dan menangkap tindanan komponen penuh, pelaksanaan, locale, timeZone, sumber tema, dan status cache. Saya akan mengekalkan respons rangkaian dan membandingkannya dengan DOM sebelum React bermula. Jika respons sudah salah, saya akan memeriksa snapshot pelayan dan CDN. Jika penghuraian mengubahnya, saya akan memeriksa penyarangan tidak sah, sambungan pelayar, dan skrip awal. Jika ia berubah hanya apabila React bermula, saya akan membandingkan props klien pertama dan cabang persekitaran.

Untuk pembaikan, pelayan akan menyelesaikan locale, timeZone, dan tema awal daripada kuki atau profil, memformat updatedLabel, dan menghantarnya bersama masa ISO. Render klien pertama akan menggunakan nilai-nilai tersebut dengan tepat. Saya akan menggantikan ID rawak dengan useId dan membetulkan semantik HTML. Maklumat pelayar yang tidak diketahui oleh pelayan akan bermula dengan pemegang tempat yang stabil dan dikemas kini dalam Effect. Data perniagaan akan bermula daripada snapshot pelayan yang disiri dan disegarkan semula di latar belakang selepas hidratasi.

Saya tidak akan menyahdayakan SSR secara global atau menyekat amaran yang boleh dibetulkan. Saya akan menggunakan ssr: false tempatan hanya untuk daun pihak ketiga pelayar sahaja, dan menyekat hanya perbezaan paparan satu tahap yang tidak dapat dielakkan. Akhir sekali, saya akan menguji pemuatan sejuk pengeluaran merentas gabungan locale, zon masa, tema, cache, rangkaian perlahan, dan pelayar bersih, mengesahkan tiada ralat #418, penggantian subpokok, kehilangan fokus, atau kelipan visual."

Kesilapan Biasa

  • Menganggap "use client" bermaksud tiada HTML pelayan. Client Component masih boleh dipramuat pada pemuatan awal.
  • Menggunakan typeof window dalam JSX untuk merender dua UI berbeza. Cabang pelayan dan render pertama pelayar secara semula jadi boleh berbeza.
  • Memindahkan setiap nilai ke dalam Effect dan mengisytiharkan kejayaan. Ini boleh menangguhkan ketakpadanan sambil menambah render kedua, kandungan kosong, anjakan reka letak (layout shifts), dan pengalaman rangkaian perlahan yang lebih teruk.
  • Menambah suppressHydrationWarning pada nod akar yang luas. Ia adalah cetek dan tidak membuatkan React menampal teks yang tidak sepadan.
  • Menukar keseluruhan halaman kepada ssr: false selepas melihat ralat pengeluaran. Ini menghapuskan nilai pramuat tanpa menjelaskan punca utamanya.
  • Hanya membandingkan View Source dengan DOM selepas hidratasi. Tindakan itu mengabaikan DOM yang dihuraikan oleh pelayar sebelum React bermula.
  • Hanya menguji pembangunan tempatan dan navigasi klien. Binaan pengeluaran, muat semula penuh, cache pinggir, zon masa, atau sambungan pelayar mungkin diperlukan untuk mencetuskan kerosakan asal.
  • Berhenti apabila konsol senyap. Pastikan juga tiada penggantian, pengendali yang salah, kehilangan fokus, kelipan visual, atau data perniagaan yang salah.

Soalan Susulan dan Jawapan

Mengapa tidak menambah suppressHydrationWarning pada setiap cap masa?

Ia adalah laluan keluar kecemasan satu tahap, dan React tidak menampal teks yang disekat untuk anda. Jika cap masa berbeza kerana kedua-dua persekitaran menggunakan zon masa lalai yang berbeza, locale dan timeZone yang eksplisit atau nilai terformat yang dikongsi akan membetulkan puncanya. Gunakan penyekatan hanya apabila produk menerima nilai pascahidratasi yang sengaja berbeza dan perbezaan itu benar-benar tidak dapat dialih keluar. Sahkan kedua-dua tingkah laku visual dan apa yang dibaca oleh teknologi bantuan (assistive technology).

Bagaimana anda memilih antara useEffect dan ssr: false?

Jika komponen mempunyai rangka (shell) yang stabil dan kandungan pramuat yang bernilai, tetapi satu label bergantung pada maklumat pelayar, kekalkan SSR dan kemas kini bahagian kecil itu selepas hidratasi. Jika keseluruhan komponen daun bergantung pada pustaka pihak ketiga yang tidak boleh dijalankan pada pelayan, tidak mempunyai output pramuat yang berguna, dan boleh menyediakan keadaan pemuatan saiz yang stabil, nyahdayakan SSR secara tempatan. Keputusan ini bergantung pada nilai kandungan, sempadan kebergantungan, dan kos visual, bukan mana-mana pilihan yang membuatkan amaran hilang paling cepat.

Bagaimana HTML tidak sah boleh merosakkan hidratasi apabila kedua-dua persekitaran menjalankan kod React yang sama?

Pelayan menghantar rentetan, dan pelayar membina serta membaiki DOM mengikut peraturan penghuraian HTML. Penyarangan yang tidak sah mungkin ditutup secara automatik, dialihkan, atau dialih keluar. Oleh itu, React mengambil alih pokok yang telah dibaiki dan bukannya pokok yang kelihatan seperti diterangkan oleh rentetan asal. Bandingkan badan respons dengan DOM pra-React, kemudian betulkan semantik dan sahkan HTML.

Bagaimana anda menambah kebolehcerapan (observability) apabila kegagalan khusus pengeluaran berlaku secara berselang-seli?

Kumpulkan ralat atau kod boleh pulih penuh, tindanan komponen, laluan, versi pelaksanaan, locale, timeZone, sumber tema, status cache, dan jenis pelayar dengan pensampelan dan penapisan privasi. Rekodkan ringkasan (digest) atau versi yang tidak boleh diundur bagi input render pertama yang kritikal supaya snapshot pelayan dan klien boleh dibandingkan tanpa merekodkan nilai sensitif. Pecahkan metrik mengikut laluan, versi, dan persekitaran. Selepas pembaikan, sahkan bahawa kadar ralat mencapai sifar dan metrik penggantian subpokok, interaksi, serta visual tidak merosot.

Sumber awam

Soalan berkaitan