TL; DR
Bagaimana komponen induk dapat mengetahui kapan rendering setiap komponen anak di bawahnya telah selesai dan DOM terlihat oleh pengguna dengan versi terbarunya?
Katakanlah saya memiliki komponen component A
anak yang Grid
terdiri dari 3x3
komponen cucu. Masing-masing komponen cucu itu mengambil data dari titik akhir API yang tenang dan membuatnya sendiri ketika data tersedia.
Saya ingin mencakup seluruh area Component A
dengan loader
placeholder, untuk diungkapkan hanya ketika komponen terakhir dalam kisi telah mengambil data dengan sukses, dan mengolahnya, sehingga sudah ada di DOM dan dapat dilihat.
Pengalaman pengguna harus menjadi transisi yang sangat mulus dari "loader" ke grid yang terisi penuh tanpa berkedip.
Masalah saya adalah mengetahui kapan tepatnya mengungkap komponen di bawah loader.
Apakah ada mekanisme yang bisa saya andalkan untuk melakukan ini dengan akurasi absolut? Saya tidak membuat kode batas waktu untuk loader. Seperti yang saya pahami bergantung ComponentDidMount
untuk setiap anak juga tidak dapat diandalkan karena sebenarnya tidak menjamin komponen sepenuhnya terlihat oleh pengguna pada saat panggilan.
Untuk menyaring pertanyaan lebih jauh:
Saya memiliki komponen yang membuat beberapa jenis data. Setelah diinisialisasi itu tidak memilikinya, jadi di
componentDidMount
dalamnya hits titik akhir API untuk itu. Setelah menerima data, itu mengubah statusnya untuk mencerminkannya. Hal ini dapat dimengerti menyebabkan re-render dari keadaan akhir komponen itu. Pertanyaan saya adalah ini: Bagaimana saya tahu kapan re-render telah terjadi dan tercermin dalam Pengguna yang menghadapi DOM. Titik waktu itu! = Titik waktu ketika keadaan komponen telah berubah menjadi berisi data.
ComponentDidMount
saya gunakanaxios
untuk mengambil data. ketika data datang, saya mengubah status komponen yang menyebabkan render data. Secara teori, 8 komponen anak dapat diambil dalam 3 detik, dan yang terakhir akan memakan waktu 15 detik ...Jawaban:
Ada dua kait siklus hidup di Bereaksi yang dipanggil setelah DOM komponen diberikan:
Untuk kasus penggunaan Anda, komponen induk Anda P tertarik ketika N komponen anak masing-masing puas beberapa kondisi X . X dapat didefinisikan sebagai urutan:
Dengan menggabungkan keadaan komponen dan menggunakan
componentDidUpdate
pengait, Anda dapat mengetahui kapan urutannya selesai dan komponen Anda memenuhi kondisi X.Anda dapat melacak kapan operasi async Anda selesai dengan menetapkan variabel status. Sebagai contoh:
Setelah mengatur keadaan, Bereaksi akan memanggil
componentDidUpdate
fungsi komponen Anda . Dengan membandingkan objek keadaan saat ini dan sebelumnya dalam fungsi ini, Anda dapat memberi sinyal ke komponen induk bahwa operasi async Anda telah selesai dan status komponen baru Anda telah dirender:Dalam komponen P Anda, Anda dapat menggunakan penghitung untuk melacak berapa banyak anak yang diperbarui secara bermakna:
Akhirnya, dengan mengetahui panjang N Anda dapat mengetahui kapan semua pembaruan yang berarti telah terjadi dan bertindak sesuai dalam metode render P Anda :
sumber
Saya akan mengaturnya sehingga Anda mengandalkan variabel kondisi global untuk memberi tahu komponen Anda kapan harus merender. Redux lebih baik untuk skenario ini di mana banyak komponen berbicara satu sama lain, dan Anda menyebutkan dalam komentar bahwa Anda kadang-kadang menggunakannya. Jadi saya akan membuat sketsa jawaban menggunakan Redux.
Anda harus memindahkan panggilan API ke wadah induk,
Component A
,. Jika Anda ingin agar cucu-cucu Anda render hanya setelah panggilan API selesai, Anda tidak dapat menyimpan panggilan API itu sendiri di cucu. Bagaimana panggilan API dapat dibuat dari komponen yang belum ada?Setelah semua panggilan API dilakukan, Anda dapat menggunakan tindakan untuk memperbarui variabel status global yang berisi banyak objek data. Setiap kali data diterima (atau kesalahan ditangkap), Anda dapat mengirim tindakan untuk memeriksa apakah objek data Anda terisi penuh. Setelah sepenuhnya terisi, Anda dapat memperbarui
loading
variabel kefalse
, dan membuat Anda kondisionalGrid
komponen .Jadi misalnya:
Peredam Anda akan memegang objek negara global yang akan mengatakan apakah semuanya siap untuk pergi atau belum:
Dalam tindakan Anda:
Ke samping
Jika Anda benar-benar menikah dengan gagasan bahwa panggilan API Anda tinggal di dalam masing-masing cucu, tetapi bahwa seluruh Kotak cucu tidak memberikan hingga semua panggilan API selesai, Anda harus menggunakan solusi yang sama sekali berbeda. Dalam hal ini, cucu Anda harus diberikan dari awal untuk melakukan panggilan, tetapi memiliki kelas css
display: none
, yang hanya berubah setelah variabel keadaan globalloading
ditandai sebagai salah. Ini juga bisa dilakukan, tetapi semacam selain dari React.sumber
Anda berpotensi memecahkan masalah ini menggunakan React Suspense.
Peringatannya adalah bahwa itu bukan ide yang baik untuk Menunda melewati pohon komponen yang melakukan render (yaitu: Jika komponen Anda memulai proses render, itu bukan ide yang baik untuk menunda komponen itu, menurut pengalaman saya), jadi mungkin ide yang lebih baik untuk memulai permintaan di komponen yang membuat sel. Sesuatu seperti ini:
Sekarang, cukup bagaimana Suspense berpasangan dengan Redux saya tidak yakin. Seluruh ide di balik versi Suspense (percobaan!) Ini adalah Anda memulai pengambilan langsung selama siklus render komponen induk dan meneruskan objek yang mewakili pengambilan kepada anak-anak. Ini mencegah Anda harus memiliki semacam objek Penghalang (yang Anda perlukan dalam pendekatan lain).
Saya akan mengatakan bahwa saya tidak berpikir menunggu sampai semuanya diambil untuk menampilkan sesuatu adalah pendekatan yang tepat karena UI akan selambat koneksi paling lambat atau mungkin tidak berfungsi sama sekali!
Berikut sisa kode yang hilang:
Dan kotak pasir: https://codesandbox.io/s/falling-dust-b8e7s
sumber
Pertama-tama, siklus hidup dapat memiliki metode asink / menunggu.
Apa yang perlu kita ketahui
componentDidMount
dancomponentWillMount
,Dalam pertimbangan saya, cukup menerapkannya menggunakan siklus hidup normal akan cukup baik.
Kemajuan Circular Material-UI
Karena rendering ulang anak menyebabkan orang tua melakukan hal yang sama, menangkapnya
didUpdate
akan baik-baik saja.Dan, karena dipanggil setelah rendering, halaman tidak boleh diubah setelah itu jika Anda mengatur fungsi cek sebagai permintaan Anda.
Kami menggunakan implementasi ini di prod kami yang memiliki api menyebabkan 30-an untuk mendapatkan respon, semua bekerja dengan baik sejauh yang saya lihat.
sumber
Ketika Anda membuat panggilan api
componentDidMount
, ketika panggilan API akan menyelesaikan Anda akan memiliki datacomponentDidUpdate
karena siklus hidup ini akan melewati AndaprevProps
danprevState
. Jadi Anda dapat melakukan sesuatu seperti di bawah ini:Jika Anda ingin mengetahui hal ini sebelum komponen dirender kembali, Anda dapat menggunakannya
getSnapshotBeforeUpdate
.https://reactjs.org/docs/react-component.html#getsnapshotbeforeupdate .
sumber
Ada beberapa pendekatan yang bisa Anda gunakan:
sumber