Salah satu keuntungan terbesar dari React.js adalah rendering sisi server . Masalahnya adalah bahwa fungsi kuncinya React.renderComponentToString()
sinkron sehingga tidak mungkin memuat data asinkron apa pun saat hierarki komponen dirender di server.
Katakanlah saya memiliki komponen universal untuk berkomentar yang dapat saya jatuhkan di mana saja di halaman. Ini hanya memiliki satu properti, beberapa jenis pengenal (misalnya id artikel di bawah ini tempat komentar ditempatkan), dan yang lainnya ditangani oleh komponen itu sendiri (memuat, menambah, mengelola komentar).
Saya sangat menyukai arsitektur Flux karena ia membuat banyak hal menjadi lebih mudah, dan tokonya sempurna untuk berbagi status antara server dan klien. Setelah toko saya yang berisi komentar diinisialisasi, saya hanya dapat membuat serial dan mengirimkannya dari server ke klien di mana ia dapat dengan mudah dipulihkan.
Pertanyaannya adalah bagaimana cara terbaik untuk mengisi toko saya. Selama beberapa hari terakhir ini saya telah banyak mencari di Google dan menemukan beberapa strategi, tidak ada satupun yang terlihat sangat bagus mengingat seberapa besar fitur React ini "dipromosikan".
Menurut pendapat saya, cara paling sederhana adalah mengisi semua toko saya sebelum rendering sebenarnya dimulai. Itu berarti di suatu tempat di luar hierarki komponen (terhubung ke router saya misalnya). Masalah dengan pendekatan ini adalah saya harus cukup banyak mendefinisikan struktur halaman dua kali. Pertimbangkan halaman yang lebih kompleks, misalnya halaman blog dengan banyak komponen berbeda (posting blog aktual, komentar, posting terkait, posting terbaru, aliran twitter ...). Saya harus mendesain struktur halaman menggunakan komponen React dan kemudian di tempat lain saya harus menentukan proses pengisian setiap toko yang diperlukan untuk halaman ini. Bagi saya, itu bukan solusi yang bagus. Sayangnya sebagian besar tutorial isomorfik dirancang dengan cara ini (misalnya tutorial fluks yang hebat ini ).
React-async . Pendekatan ini sempurna. Ini memungkinkan saya untuk menentukan dalam fungsi khusus di setiap komponen bagaimana menginisialisasi status (tidak peduli apakah secara sinkron atau asinkron) dan fungsi ini disebut sebagai hierarki yang dirender ke HTML. Ia bekerja sedemikian rupa sehingga komponen tidak dirender hingga status benar-benar diinisialisasi. Masalahnya adalah itu membutuhkan Seratyang, sejauh yang saya pahami, ekstensi Node.js yang mengubah perilaku JavaScript standar. Meskipun saya sangat menyukai hasilnya, saya tetap merasa bahwa alih-alih menemukan solusi, kami mengubah aturan permainan. Dan saya pikir kita seharusnya tidak dipaksa melakukan itu untuk menggunakan fitur inti React.js ini. Saya juga tidak yakin tentang dukungan umum dari solusi ini. Apakah mungkin menggunakan Fiber pada hosting web Node.js standar?
Saya berpikir sedikit sendiri. Saya belum benar-benar memikirkan detail implementasi tetapi gagasan umumnya adalah bahwa saya akan memperluas komponen dengan cara yang mirip dengan React-async dan kemudian saya akan berulang kali memanggil React.renderComponentToString () pada komponen root. Selama setiap pass, saya akan mengumpulkan callback yang diperpanjang dan kemudian memanggil mereka di dan dari pass untuk mengisi toko. Saya akan mengulangi langkah ini sampai semua penyimpanan yang diperlukan oleh hierarki komponen saat ini akan terisi. Ada banyak hal yang harus diselesaikan dan saya sangat tidak yakin dengan penampilannya.
Apakah saya melewatkan sesuatu? Apakah ada pendekatan / solusi lain? Saat ini saya sedang berpikir untuk menggunakan cara react-async / fibres tetapi saya tidak sepenuhnya yakin tentang hal itu seperti yang dijelaskan pada poin kedua.
Diskusi terkait di GitHub . Ternyata, tidak ada pendekatan resmi atau bahkan solusi. Mungkin pertanyaan sebenarnya adalah bagaimana komponen React dimaksudkan untuk digunakan. Seperti lapisan tampilan sederhana (cukup banyak saran saya nomor satu) atau seperti komponen mandiri dan mandiri nyata?
sumber
Jawaban:
Jika Anda menggunakan react-router , Anda cukup menentukan
willTransitionTo
metode dalam komponen, yang akan meneruskanTransition
objek yang dapat Anda panggil.wait
.Tidak masalah jika renderToString sinkron karena callback ke
Router.run
tidak akan dipanggil hingga semua.wait
janji ed diselesaikan, jadi pada saatrenderToString
dipanggil di middleware, Anda dapat mengisi penyimpanan. Bahkan jika penyimpanannya lajang, Anda dapat menyetel datanya untuk sementara waktu tepat sebelum panggilan rendering sinkron dan komponen akan melihatnya.Contoh middleware:
The
routes
objek (yang menggambarkan hirarki rute) dibagi verbatim dengan klien dan serversumber
willTransitionTo
metode ini . Artinya, masih tidak mungkin untuk menulis komponen yang sepenuhnya dapat digunakan kembali mandiri seperti yang saya jelaskan dalam pertanyaan. Tetapi kecuali kami bersedia menggunakan Serat, ini mungkin cara terbaik dan paling bereaksi untuk menerapkan rendering sisi server.transition
objek sebagai parameter, jadi Anda cukup memanggiltransition.wait(yourPromise)
. Itu tentu saja berarti Anda harus mengimplementasikan API Anda untuk mendukung promise. Kerugian lain dari pendekatan ini adalah tidak ada cara sederhana untuk mengimplementasikan "indikator pemuatan" di sisi klien. Transisi tidak akan beralih ke komponen pengendali rute sampai semua janji diselesaikan..waited
untuk transisi. Setelah semuanya terpenuhi,.run
callback dipanggil. Tepat sebelum.render()
saya mengumpulkan semua data bersama-sama dari promise dan menetapkan status singelton store, lalu pada baris berikutnya setelah panggilan render, saya menginisialisasi penyimpanan singleton kembali. Ini cukup hacky tetapi semuanya terjadi secara otomatis dan kode aplikasi komponen dan penyimpanan tetap hampir sama.Saya tahu ini mungkin bukan yang Anda inginkan, dan mungkin tidak masuk akal, tetapi saya ingat berhasil sedikit memodifikasi komponen untuk menangani keduanya:
Jadi sesuatu seperti:
Maaf, saya tidak memiliki kode persisnya, jadi ini mungkin tidak berhasil, tetapi saya memposting untuk kepentingan diskusi.
Sekali lagi, idenya adalah untuk mengobati sebagian besar komponen sebagai pandangan bodoh, dan berurusan dengan mengambil data sebanyak mungkin keluar dari komponen.
sumber
<script type=application/json>{initState}</script>
; dengan begitu data akan berada di HTML. Rehidrasi / ikat peristiwa UI ke halaman dengan memanggil render pada klien. Halaman selanjutnya dibuat oleh kode js klien (mengambil data sesuai kebutuhan) dan diberikan oleh klien. Dengan cara itu setiap penyegaran akan memuat halaman SSR baru & mengklik halaman akan menjadi CSR. = isomorfik & SEO friendlySaya benar-benar mengacaukannya hari ini, dan meskipun ini bukan jawaban untuk masalah Anda, saya telah menggunakan pendekatan ini. Saya ingin menggunakan Express untuk perutean daripada React Router, dan saya tidak ingin menggunakan Serat karena saya tidak memerlukan dukungan threading di node.
Jadi saya baru saja membuat keputusan bahwa untuk data awal yang perlu diberikan ke penyimpanan fluks saat dimuat, saya akan melakukan permintaan AJAX dan meneruskan data awal ke penyimpanan
Saya menggunakan Fluxxor untuk contoh ini.
Jadi pada rute ekspres saya, dalam hal ini
/products
rute:Kemudian saya menginisialisasi metode render yang meneruskan data ke toko.
sumber
Saya tahu pertanyaan ini ditanyakan setahun yang lalu tetapi kami memiliki masalah yang sama dan kami menyelesaikannya dengan janji bertingkat yang berasal dari komponen yang akan dirender. Pada akhirnya kami memiliki semua data untuk aplikasi dan mengirimkannya begitu saja.
Sebagai contoh:
dan di router
sumber
Ingin berbagi dengan Anda pendekatan saya tentang rendering sisi server menggunakan
Flux
, sedikit disederhanakan misalnya:Katakanlah kita memiliki
component
data awal dari toko:Jika kelas memerlukan beberapa data pramuat untuk keadaan awal, mari buat Loader untuk
MyComponent
:Toko:
Sekarang muat saja data di router:
sumber
hanya sebagai rollup singkat -> GraphQL akan menyelesaikan ini dengan entri untuk tumpukan Anda ...
-> getDataFromTree akan secara otomatis menemukan semua kueri yang terlibat di aplikasi Anda dan menjalankannya, memisahkan cache apollo Anda di server dan dengan demikian, memungkinkan SSR yang berfungsi penuh .. BÄM
sumber