Saya baru saja mulai dengan ReactJS dan saya sedikit terjebak pada masalah yang saya miliki.
Aplikasi saya pada dasarnya adalah daftar dengan filter dan tombol untuk mengubah tata letak. Saat ini saya menggunakan tiga komponen: <list />
, < Filters />
dan <TopBar />
, sekarang jelas ketika saya mengubah pengaturan di < Filters />
Saya ingin memicu beberapa metode dalam <list />
untuk memperbarui pandangan saya.
Bagaimana saya bisa membuat 3 komponen berinteraksi satu sama lain, atau apakah saya memerlukan semacam model data global di mana saya bisa membuat perubahan?
javascript
reactjs
woutr_be
sumber
sumber
Jawaban:
Pendekatan terbaik akan tergantung pada bagaimana Anda berencana untuk mengatur komponen-komponen itu. Beberapa contoh skenario yang muncul saat ini:
<Filters />
adalah komponen anak dari<List />
<Filters />
dan<List />
merupakan anak-anak dari komponen orang tua<Filters />
dan<List />
hidup dalam komponen root yang terpisah sepenuhnya.Mungkin ada skenario lain yang tidak saya pikirkan. Jika milik Anda tidak sesuai dengan ini, maka beri tahu saya. Berikut adalah beberapa contoh kasar tentang bagaimana saya menangani dua skenario pertama:
Skenario 1
Anda bisa meneruskan pawang dari
<List />
ke<Filters />
, yang kemudian bisa dipanggil padaonChange
acara untuk menyaring daftar dengan nilai saat ini.JSFiddle untuk # 1 →
Skenario # 2
Mirip dengan skenario # 1, tetapi komponen induk akan menjadi yang meneruskan fungsi pengendali
<Filters />
, dan akan meneruskan daftar yang difilter ke<List />
. Saya suka metode ini lebih baik karena memisahkan<List />
dari<Filters />
.JSFiddle untuk # 2 →
Skenario # 3
Ketika komponen tidak dapat berkomunikasi antara hubungan orangtua-anak, dokumentasi merekomendasikan pembuatan sistem acara global .
sumber
updateFilter
untuk<Filters />
dan arrayitems
untuk<List />
. Anda bisa menggunakan komponen anak-anak itu pada orang tua lain dengan perilaku berbeda, baik bersama atau sendiri. Misalnya, jika Anda ingin menampilkan daftar dinamis tetapi tidak perlu pemfilteran.Ada beberapa cara untuk membuat komponen berkomunikasi. Beberapa dapat cocok dengan usecase Anda. Berikut adalah daftar yang menurut saya berguna untuk diketahui.
Reaksi
Komunikasi langsung orang tua / anak
Di sini komponen anak akan memanggil panggilan balik yang diberikan oleh orang tua dengan nilai, dan orang tua akan bisa mendapatkan nilai yang diberikan oleh anak-anak pada orang tua.
Jika Anda membangun fitur / halaman aplikasi Anda, lebih baik memiliki orang tua tunggal yang mengelola panggilan balik / negara bagian (juga disebut
container
atausmart component
), dan semua anak tidak memiliki kewarganegaraan, hanya melaporkan hal-hal kepada orang tua. Dengan cara ini Anda dapat dengan mudah "membagikan" keadaan orang tua kepada setiap anak yang membutuhkannya.Konteks
Bereaksi Konteks memungkinkan untuk mempertahankan status pada akar hierarki komponen Anda, dan dapat menyuntikkan status ini dengan mudah ke komponen bersarang yang sangat dalam, tanpa harus repot-repot menyerahkan props ke setiap komponen perantara.
Sampai sekarang, konteks adalah fitur eksperimental, tetapi API baru tersedia di Bereaksi 16.3.
Konsumen menggunakan pola fungsi penyangga / anak-anak
Lihat posting blog ini untuk lebih jelasnya.
Sebelum Bereaksi 16.3, saya akan merekomendasikan menggunakan siaran reaksi yang menawarkan API yang sangat mirip, dan menggunakan API konteks sebelumnya.
Portal
Gunakan portal ketika Anda ingin menjaga 2 komponen tetap berdekatan agar mereka berkomunikasi dengan fungsi-fungsi sederhana, seperti pada orang tua / anak normal, tetapi Anda tidak ingin kedua komponen ini memiliki hubungan orang tua / anak di DOM, karena kendala visual / CSS yang disiratkannya (seperti z-index, opacity ...).
Dalam hal ini Anda dapat menggunakan "portal". Ada berbagai perpustakaan reaksi yang menggunakan portal , biasanya digunakan untuk modals , popup, tooltips ...
Pertimbangkan yang berikut ini:
Dapat menghasilkan DOM berikut saat dirender di dalam
reactAppContainer
:Lebih detail di sini
Slot
Anda menentukan slot di suatu tempat, dan kemudian Anda mengisi slot dari tempat lain dari render tree Anda.
Ini agak mirip dengan portal kecuali konten yang diisi akan diberikan dalam slot yang Anda tentukan, sementara portal umumnya membuat simpul dom baru (sering kali anak-anak document.body)
Periksa pustaka slot-isi reaksi
Bus acara
Sebagaimana dinyatakan dalam dokumentasi Bereaksi :
Ada banyak hal yang dapat Anda gunakan untuk mengatur bus acara. Anda bisa membuat susunan pendengar, dan pada acara penerbitan, semua pendengar akan menerima acara tersebut. Atau Anda dapat menggunakan sesuatu seperti EventEmitter atau PostalJs
Aliran
Flux pada dasarnya adalah sebuah bus acara, kecuali penerima acara adalah toko. Ini mirip dengan sistem bus peristiwa dasar kecuali negara dikelola di luar Bereaksi
Implementasi Flux asli terlihat seperti upaya untuk melakukan Event-sourcing dengan cara yang hacky.
Redux bagi saya implementasi Flux yang paling dekat dari event-sourcing, manfaat banyak keuntungan event-sourcing seperti kemampuan untuk melakukan perjalanan waktu. Itu tidak benar-benar terkait dengan Bereaksi dan juga dapat digunakan dengan perpustakaan tampilan fungsional lainnya.
Tutorial video Redux dari Egghead sangat bagus dan menjelaskan cara kerjanya secara internal (sangat sederhana).
Kursor
Kursor berasal dari ClojureScript / Om dan banyak digunakan dalam proyek Bereaksi. Mereka mengizinkan untuk mengelola keadaan di luar Bereaksi, dan membiarkan beberapa komponen memiliki akses baca / tulis ke bagian yang sama dari negara tersebut, tanpa perlu tahu apa-apa tentang pohon komponen.
Banyak implementasi yang ada, termasuk ImmutableJS , React-cursors dan Omniscient
Sunting 2016 : tampaknya orang setuju kursor berfungsi dengan baik untuk aplikasi yang lebih kecil tetapi tidak dapat diukur dengan baik pada aplikasi kompleks. Om Next tidak memiliki kursor lagi (sementara itu Om yang memperkenalkan konsep awalnya)
Arsitektur Elm
The arsitektur Elm adalah arsitektur yang diusulkan untuk digunakan oleh bahasa Elm . Bahkan jika Elm bukan ReactJS, arsitektur Elm dapat dilakukan di React juga.
Dan Abramov, penulis Redux, melakukan implementasi arsitektur Elm menggunakan React.
Baik Redux dan Elm benar-benar hebat dan cenderung memberdayakan konsep-konsep sumber acara di frontend, keduanya memungkinkan debugging perjalanan-waktu, undo / redo, replay ...
Perbedaan utama antara Redux dan Elm adalah bahwa Elm cenderung jauh lebih ketat tentang manajemen negara. Di Elm, Anda tidak dapat memiliki status komponen lokal atau memasang / melepas kait dan semua perubahan DOM harus dipicu oleh perubahan keadaan global. Arsitektur Elm mengusulkan pendekatan terukur yang memungkinkan untuk menangani SEMUA keadaan di dalam objek tunggal yang tidak dapat diubah, sementara Redux mengusulkan pendekatan yang mengundang Anda untuk menangani PALING keadaan di dalam satu objek tak berubah.
Meskipun model konseptual Elm sangat elegan dan arsitektur memungkinkan untuk mengukur dengan baik pada aplikasi besar, dalam praktiknya dapat menjadi sulit atau melibatkan lebih banyak pelat untuk mencapai tugas-tugas sederhana seperti memberikan fokus pada input setelah pemasangan, atau mengintegrasikan dengan perpustakaan yang ada dengan antarmuka imperatif (yaitu plugin JQuery). Masalah terkait .
Juga, arsitektur Elm melibatkan lebih banyak kode boilerplate. Bukan verbose atau rumit untuk menulis tapi saya pikir arsitektur Elm lebih cocok untuk bahasa yang diketik secara statis.
FRP
Perpustakaan seperti RxJS, BaconJS atau Kefir dapat digunakan untuk menghasilkan aliran FRP untuk menangani komunikasi antar komponen.
Anda dapat mencoba misalnya Rx-React
Saya pikir menggunakan lib ini sangat mirip dengan menggunakan apa yang ditawarkan bahasa ELM dengan sinyal .
Kerangka kerja CycleJS tidak menggunakan ReactJS tetapi menggunakan vdom . Ini berbagi banyak kesamaan dengan arsitektur Elm (tetapi lebih mudah digunakan dalam kehidupan nyata karena memungkinkan kait vdom) dan menggunakan RxJ secara luas alih-alih fungsi, dan dapat menjadi sumber inspirasi yang baik jika Anda ingin menggunakan FRP dengan Reaksi. Video CycleJs Egghead bagus untuk memahami cara kerjanya.
CSP
CSP (Communicating Sequential Processes) saat ini populer (kebanyakan karena Go / goroutine dan core.async / ClojureScript) tetapi Anda dapat menggunakannya juga dalam javascript dengan JS-CSP .
James Long telah melakukan video yang menjelaskan bagaimana itu dapat digunakan dengan React.
Sagas
Saga adalah konsep backend yang berasal dari dunia DDD / EventSourcing / CQRS, juga disebut "manajer proses". Itu sedang dipopulerkan oleh proyek redux-saga , sebagian besar sebagai pengganti redux-thunk untuk menangani efek samping (yaitu panggilan API dll). Sebagian besar orang saat ini berpikir itu hanya layanan untuk efek samping tetapi sebenarnya lebih lanjut tentang komponen decoupling.
Ini lebih merupakan pujian untuk arsitektur Flux (atau Redux) daripada sistem komunikasi yang sama sekali baru, karena kisah ini memancarkan tindakan Flux pada akhirnya. Idenya adalah bahwa jika Anda memiliki widget1 dan widget2, dan Anda ingin mereka dipisahkan, Anda tidak dapat memecat penargetan tindakan widget2 dari widget1. Jadi, Anda membuat widget1 hanya melakukan aksi yang menargetkan dirinya sendiri, dan kisahnya adalah "proses latar belakang" yang mendengarkan tindakan widget1, dan dapat mengirimkan tindakan yang menargetkan widget2. Saga adalah titik penghubung antara 2 widget tetapi widget tetap dipisahkan.
Jika Anda tertarik lihat jawaban saya di sini
Kesimpulan
Jika Anda ingin melihat contoh aplikasi kecil yang sama menggunakan gaya berbeda ini, periksa cabang repositori ini .
Saya tidak tahu apa pilihan terbaik dalam jangka panjang, tetapi saya sangat suka bagaimana Flux terlihat seperti sumber acara.
Jika Anda tidak tahu konsep acara-sumber, lihatlah blog sangat pedagogik ini: Beralih di dalam basis data dengan apache Samza , itu adalah suatu keharusan-baca untuk memahami mengapa Flux bagus (tapi ini bisa berlaku untuk FRP serta )
Saya pikir komunitas setuju bahwa implementasi Flux yang paling menjanjikan adalah Redux , yang akan semakin memungkinkan pengalaman pengembang yang sangat produktif berkat pemuatan ulang yang panas. Video live yang mengesankan ala Bret Victor's Inventing on Principle video dimungkinkan!
sumber
OK, ada beberapa cara untuk melakukannya, tetapi saya secara eksklusif ingin fokus menggunakan toko menggunakan Redux yang membuat hidup Anda lebih mudah untuk situasi ini daripada memberikan Anda solusi cepat hanya untuk kasus ini, menggunakan pure React akan berakhir berantakan di aplikasi besar nyata dan komunikasi antara Komponen menjadi semakin sulit saat aplikasi tumbuh ...
Jadi apa yang Redux lakukan untuk Anda?
Redux seperti penyimpanan lokal di aplikasi Anda yang dapat digunakan kapan pun Anda membutuhkan data untuk digunakan di berbagai tempat di aplikasi Anda ...
Pada dasarnya, ide Redux berasal dari fluks awalnya, tetapi dengan beberapa perubahan mendasar termasuk konsep memiliki satu sumber kebenaran dengan menciptakan hanya satu toko ...
Lihatlah grafik di bawah ini untuk melihat beberapa perbedaan antara Flux dan Redux ...
Pertimbangkan penerapan Redux di aplikasi Anda sejak awal jika aplikasi Anda membutuhkan komunikasi antar Komponen ...
Juga membaca kata-kata ini dari Dokumentasi Redux bisa membantu untuk memulai dengan:
sumber
datepicker
(sebagai komponen) dan komponen itu dapat dimuat dari beberapa komponen yang hidup di halaman yang sama, lalu bagaimanadatepicker
komponen itu tahu Tindakan yang harus dikirim ke redux? Ini adalah inti dari masalah, menghubungkan suatu tindakan dalam satu komponen dengan komponen lainnya dan BUKAN komponen lainnya . (Mempertimbangkandatepicker
sendiri itu adalah komponen yang dalam dan dalam di dalam komponen modal itu sendiri)redux
dan apa yang bisa Anda simpan, tetapi BAGAIMANA untuk meneruskan tindakan itu jauh ke dalam apa yang perlu memicu itu. Bagaimana komponen yang dalam tahu apa yang perlu dipicu secara PERSIS ? karena dalam contoh saya memberikan komponen umum yang harus memicu ke peredam tertentu, tergantung pada skenario, sehingga bisa menjadi peredam yang berbeda karena modal datepicker dapat digunakan untuk komponen apa pun.Ini cara saya menangani ini.
Katakanlah Anda memiliki <seleksi> untuk Bulan dan <seleksi> untuk Hari . Jumlah hari tergantung pada bulan yang dipilih.
Kedua daftar dimiliki oleh objek ketiga, panel kiri. Keduanya <select> juga anak-anak dari leftPanel <div>
Ini adalah game dengan callback dan penangan dalam komponen LeftPanel .
Untuk mengujinya, cukup salin kode ke dua file yang terpisah dan jalankan index.html . Kemudian pilih satu bulan dan lihat bagaimana jumlah hari berubah.
tanggal.js
Dan HTML untuk menjalankan index.html komponen panel kiri
sumber
Saya melihat bahwa pertanyaannya sudah dijawab, tetapi jika Anda ingin mempelajari lebih lanjut, ada total 3 kasus komunikasi antar komponen :
sumber
Memperluas jawaban dari @MichaelLaCroix ketika sebuah skenario adalah bahwa komponen tidak dapat berkomunikasi antara segala jenis hubungan orangtua-anak, dokumentasi merekomendasikan untuk menyiapkan sistem acara global.
Dalam kasus
<Filters />
dan<TopBar />
tidak memiliki hubungan di atas, emitor global sederhana dapat digunakan seperti ini:componentDidMount
- Berlangganan acaracomponentWillUnmount
- Berhenti berlangganan dari acaraReact.js dan kode EventSystem
EventSystem.js
NotificationComponent.js
sumber
Ada kemungkinan seperti itu bahkan jika mereka bukan orang tua - hubungan anak - dan itu fluks. Ada implementasi (untuk saya pribadi) yang cukup bagus untuk yang disebut Alt.JS (dengan Alt-Container).
Misalnya, Anda dapat memiliki Bilah Samping yang bergantung pada apa yang diatur dalam Rincian komponen. Sidebar Komponen terhubung dengan SidebarActions dan SidebarStore, sedangkan Detail adalah DetailsActions dan DetailsStore.
Anda bisa menggunakan AltContainer lalu seperti itu
Yang akan menyimpan toko (baik saya bisa menggunakan "toko" bukan prop "toko"). Sekarang, {this.props.content} BISA MENJADI Detail tergantung pada rute. Mari kita katakan / Detail mengarahkan kita ke tampilan itu. Detail akan memiliki misalnya kotak centang yang akan mengubah elemen Sidebar dari X ke Y jika akan diperiksa.
Secara teknis tidak ada hubungan di antara mereka dan itu akan sulit dilakukan tanpa fluks. TETAPI DENGAN ITU agak mudah.
Sekarang mari kita ke DetailsActions. Kami akan membuat di sana
dan DetailsStore
Dan sekarang, ini adalah tempat di mana sihir dimulai.
Seperti yang Anda lihat ada bindListener ke SidebarActions.ComponentStatusChanged yang akan digunakan JIKA setSiteComponent akan digunakan.
sekarang di SidebarActions
Kami punya hal seperti itu. Ini akan mengirimkan objek itu saat dipanggil. Dan itu akan dipanggil jika setSiteComponent di store akan digunakan (yang dapat Anda gunakan dalam komponen misalnya selama onChange on Button atau apa pun)
Sekarang di SidebarStore akan kita miliki
Sekarang di sini Anda dapat melihat, bahwa ia akan menunggu DetailsStore. Apa artinya? lebih atau kurang itu berarti bahwa metode ini perlu menunggu pembaruan DetailsStoreto sebelum dapat memperbarui sendiri.
tl; dr One Store mendengarkan metode di toko, dan akan memicu tindakan dari tindakan komponen, yang akan memperbarui toko sendiri.
Saya harap ini bisa membantu Anda.
sumber
Jika Anda ingin menjelajahi opsi komunikasi antar komponen dan merasa semakin sulit, maka Anda dapat mempertimbangkan untuk mengadopsi pola desain yang baik: Flux .
Ini hanyalah kumpulan aturan yang menentukan bagaimana Anda menyimpan dan mengubah status aplikasi yang luas, dan menggunakan status tersebut untuk membuat komponen.
Ada banyak implementasi Flux, dan implementasi resmi Facebook adalah salah satunya. Meskipun dianggap salah satu yang berisi sebagian besar kode boilerplate, tetapi lebih mudah dipahami karena sebagian besar hal-hal itu eksplisit.
Beberapa alternatif lainnya adalah membingungkan fluxxor fluxible dan redux .
sumber
Saya pernah berada di tempat Anda berada sekarang, sebagai seorang pemula Anda kadang merasa tidak pada tempatnya tentang bagaimana reaksinya melakukan hal ini. Saya akan mencoba untuk menangani cara yang sama yang saya pikirkan sekarang.
Negara adalah landasan komunikasi
Biasanya apa yang turun adalah cara Anda mengubah keadaan dalam komponen ini dalam kasus Anda, Anda menunjukkan tiga komponen.
<List />
: Yang mungkin akan menampilkan daftar item tergantung pada filter<Filters />
: Opsi filter yang akan mengubah data Anda.<TopBar />
: Daftar opsi.Untuk mengatur semua interaksi ini, Anda akan memerlukan komponen yang lebih tinggi, sebut saja Aplikasi, yang akan meneruskan tindakan dan data ke masing-masing komponen ini sehingga misalnya dapat terlihat seperti ini
Jadi ketika
setFilter
dipanggil itu akan mempengaruhi filteredItem dan merender ulang kedua komponen ;. Dalam hal ini tidak sepenuhnya jelas saya membuat Anda contoh dengan kotak centang yang dapat Anda periksa dalam satu file:sumber
Kode berikut membantu saya mengatur komunikasi antara dua saudara kandung. Penyiapan dilakukan di induknya selama panggilan render () dan componentDidMount (). Ini didasarkan pada https://reactjs.org/docs/refs-and-the-dom.html Semoga ini bisa membantu.
sumber
Anehnya tidak ada yang disebutkan
mobx
. Idenya mirip denganredux
. Jika saya memiliki sepotong data yang berlangganan beberapa komponen, maka saya dapat menggunakan data ini untuk mendorong banyak komponen.sumber