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
const Child = ({fromChildToParentCallback}) => (
<div onClick={() => fromChildToParentCallback(42)}>
Click me
</div>
);
class Parent extends React.Component {
receiveChildValue = (value) => {
console.log("Parent received value from child: " + value); // value is 42
};
render() {
return (
<Child fromChildToParentCallback={this.receiveChildValue}/>
)
}
}
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
atau smart 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.
const AppContext = React.createContext(null)
class App extends React.Component {
render() {
return (
<AppContext.Provider value={{language: "en",userId: 42}}>
<div>
...
<SomeDeeplyNestedComponent/>
...
</div>
</AppContext.Provider>
)
}
};
const SomeDeeplyNestedComponent = () => (
<AppContext.Consumer>
{({language}) => <div>App language is currently {language}</div>}
</AppContext.Consumer>
);
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:
<div className="a">
a content
<Portal target="body">
<div className="b">
b content
</div>
</Portal>
</div>
Dapat menghasilkan DOM berikut saat dirender di dalam reactAppContainer
:
<body>
<div id="reactAppContainer">
<div className="a">
a content
</div>
</div>
<div className="b">
b content
</div>
</body>
Lebih detail di sini
Slot
Anda menentukan slot di suatu tempat, dan kemudian Anda mengisi slot dari tempat lain dari render tree Anda.
import { Slot, Fill } from 'react-slot-fill';
const Toolbar = (props) =>
<div>
<Slot name="ToolbarContent" />
</div>
export default Toolbar;
export const FillToolbar = ({children}) =>
<Fill name="ToolbarContent">
{children}
</Fill>
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 :
Untuk komunikasi antara dua komponen yang tidak memiliki hubungan orangtua-anak, Anda dapat mengatur sistem acara global Anda sendiri. Berlangganan acara di componentDidMount (), berhenti berlangganan di componentWillUnmount (), dan panggil setState () saat Anda menerima suatu peristiwa.
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!