Apakah tidak ada cara sederhana untuk mengirimkan anak props
ke orang tuanya menggunakan acara, di React.js?
var Child = React.createClass({
render: function() {
<a onClick={this.props.onClick}>Click me</a>
}
});
var Parent = React.createClass({
onClick: function(event) {
// event.component.props ?why is this not available?
},
render: function() {
<Child onClick={this.onClick} />
}
});
Saya tahu Anda dapat menggunakan komponen yang dikontrol untuk memberikan nilai input tetapi akan lebih baik untuk melewatkan keseluruhan kit n 'kaboodle. Terkadang komponen anak berisi serangkaian informasi yang Anda lebih suka tidak perlu mencari.
Mungkin ada cara untuk mengikat komponen ke acara tersebut?
UPDATE - 9/1/2015
Setelah menggunakan React selama lebih dari setahun, dan didorong oleh jawaban Sebastien Lorber, saya telah menyimpulkan melewati komponen anak sebagai argumen untuk fungsi pada orang tua sebenarnya bukan cara Bereaksi, juga bukan ide yang bagus. Saya sudah mengganti jawabannya.
javascript
reactjs
KendallB
sumber
sumber
Jawaban:
Sunting : lihat contoh akhir untuk contoh terbaru ES6.
Jawaban ini hanya menangani kasus hubungan orangtua-anak langsung. Ketika orang tua dan anak berpotensi memiliki banyak perantara, periksa jawaban ini .
Solusi lain tidak ada gunanya
Sementara mereka masih bekerja dengan baik, jawaban lain kehilangan sesuatu yang sangat penting.
Orang tua sudah memiliki properti anak itu! : jika anak memiliki alat peraga, maka itu karena orang tuanya menyediakan alat peraga itu kepada anak itu! Mengapa Anda ingin anak itu memberikan kembali prop kepada orang tua, sementara orangtua jelas sudah memiliki prop itu?
Implementasi yang lebih baik
Anak : itu benar-benar tidak harus lebih rumit dari itu.
Orang tua dengan anak tunggal : menggunakan nilai yang diberikan kepada anak
JsFiddle
Orangtua dengan daftar anak : Anda masih memiliki semua yang Anda butuhkan pada orang tua dan tidak perlu membuat anak lebih rumit.
JsFiddle
Dimungkinkan juga untuk digunakan
this.handleChildClick.bind(null,childIndex)
dan kemudian digunakanthis.state.childrenData[childIndex]
Catatan kami mengikat dengan
null
konteks karena jika tidak Bereaksi mengeluarkan peringatan yang terkait dengan sistem autobinding -nya . Menggunakan null berarti Anda tidak ingin mengubah konteks fungsi. Lihat juga .Tentang enkapsulasi dan penggabungan dalam jawaban lain
Bagi saya ini adalah ide buruk dalam hal kopling dan enkapsulasi:
Menggunakan alat peraga : Seperti yang saya jelaskan di atas, Anda sudah memiliki alat peraga di induk sehingga tidak berguna untuk melewatkan seluruh komponen anak untuk mengakses alat peraga.
Menggunakan referensi : Anda sudah memiliki target klik dalam acara tersebut, dan dalam kebanyakan kasus ini sudah cukup. Selain itu, Anda bisa menggunakan referensi langsung pada anak:
Dan akses simpul DOM di induk dengan
Untuk kasus yang lebih lanjut di mana Anda ingin mengakses beberapa referensi anak di orang tua, anak tersebut dapat melewati semua node dom langsung di callback.
Komponen memiliki antarmuka (alat peraga) dan orang tua tidak boleh menganggap apa pun tentang pekerjaan batin anak, termasuk struktur DOM bagian dalamnya atau yang dideklarasikan oleh simpul DOM. Orang tua yang menggunakan referensi anak berarti Anda memasangkan kedua komponen tersebut dengan erat.
Untuk mengilustrasikan masalah ini, saya akan mengambil kutipan ini tentang Shadow DOM , yang digunakan di dalam browser untuk membuat hal-hal seperti slider, scrollbars, pemutar video ...:
Masalahnya adalah bahwa jika Anda membiarkan detail implementasi anak bocor ke orang tua, Anda membuatnya sangat sulit untuk refactor anak tanpa mempengaruhi orang tua. Ini berarti sebagai penulis perpustakaan (atau sebagai editor peramban dengan Shadow DOM) ini sangat berbahaya karena Anda membiarkan klien mengakses terlalu banyak, sehingga sangat sulit untuk memutakhirkan kode tanpa melanggar retrokompatibilitas.
Jika Chrome telah menerapkan bilah gulirnya sehingga klien dapat mengakses node dom bagian dalam bilah gulir itu, ini berarti bahwa klien mungkin memiliki kemungkinan untuk hanya menghancurkan bilah gulir itu, dan bahwa aplikasi akan lebih mudah pecah ketika Chrome melakukan pembaruan otomatis setelah refactoring. scrollbar ... Alih-alih, mereka hanya memberikan akses ke beberapa hal yang aman seperti menyesuaikan beberapa bagian scrollbar dengan CSS.
Tentang menggunakan hal lain
Melewati seluruh komponen dalam panggilan balik itu berbahaya dan dapat menyebabkan pengembang pemula melakukan hal-hal yang sangat aneh seperti menelepon
childComponent.setState(...)
atauchildComponent.forceUpdate()
, atau menugaskannya variabel baru, di dalam induk, membuat seluruh aplikasi jauh lebih sulit untuk dipikirkan.Edit: contoh ES6
Seperti banyak orang sekarang menggunakan ES6, berikut adalah contoh yang sama untuk sintaks ES6
Anak itu bisa sangat sederhana:
Orang tua dapat berupa kelas (dan akhirnya dapat mengelola negara itu sendiri, tapi saya meneruskannya sebagai alat peraga di sini:
Tetapi ini juga dapat disederhanakan jika tidak perlu mengatur status:
JsFiddle
PERF PERINGATAN (berlaku untuk ES5 / ES6): jika Anda menggunakan
PureComponent
ataushouldComponentUpdate
, implementasi di atas tidak akan dioptimalkan secara default karena menggunakanonClick={e => doSomething()}
, atau mengikat langsung selama fase render, karena itu akan membuat fungsi baru setiap kali orangtua membuat. Jika ini adalah hambatan utama dalam aplikasi Anda, Anda dapat meneruskan data kepada anak-anak, dan memasukkannya kembali ke dalam panggilan balik "stabil" (ditetapkan pada kelas induk, dan diikat kethis
dalam konstruktor kelas) sehinggaPureComponent
optimisasi dapat dimulai, atau Anda dapat menerapkan sendirishouldComponentUpdate
dan mengabaikan panggilan balik dalam pemeriksaan perbandingan alat peraga.Anda juga dapat menggunakan pustaka komposisi ulang , yang menyediakan komponen pesanan lebih tinggi untuk mencapai optimisasi yang disempurnakan:
Dalam hal ini Anda dapat mengoptimalkan komponen Anak dengan menggunakan:
sumber
props
. Setuju?How do I know which of my children was chosen among a group?
ini bukan bagian dari pertanyaan awal, tapi saya memasukkan solusi dalam jawaban saya. Tidak seperti hasil edit Anda, saya pikir tidak perlu memodifikasi anak sama sekali, bahkan ketika berhadapan dengan daftar, seperti yang dapat Anda gunakanbind
langsung di induknya.onClick={this.handleChildClick.bind(null,childData)}
Anda sebutkan tentang autobinding Apakah ini masih berlaku sekarang karena React belum termasuk dalam model kelas . Saya sudah membaca banyak hal tetapi bagian ini masih membingungkan saya. Saya menggunakan ES6class model
omong-omong, jadi aku berubahnull
kethis
dan kode saya tampaknya masih bekerja. Bagaimana Anda menerjemahkan bagian kode Anda menjadi gaya ES6?Pembaruan (9/1/15): OP telah menjadikan pertanyaan ini sebagai target yang bergerak. Sudah diperbarui lagi. Jadi, saya merasa bertanggung jawab untuk memperbarui balasan saya.
Pertama, jawaban untuk contoh yang Anda berikan:
Ya, ini mungkin.
Anda dapat menyelesaikan ini dengan memperbarui Child's
onClick
menjadithis.props.onClick.bind(null, this)
:Penangan acara di Induk Anda kemudian dapat mengakses komponen dan acara seperti:
Snapshot JSBin
Tetapi pertanyaan itu sendiri menyesatkan
Orang tua sudah tahu Anak
props
.Ini tidak jelas dalam contoh yang diberikan karena tidak ada alat peraga yang benar-benar disediakan. Kode sampel ini mungkin lebih baik mendukung pertanyaan yang diajukan:
Menjadi lebih jelas dalam contoh ini bahwa Anda sudah tahu alat peraga Anak.
Snapshot JSBin
Jika ini benar-benar tentang menggunakan alat peraga Anak ...
Jika ini benar-benar tentang menggunakan alat peraga Anak, Anda dapat menghindari hubungan dengan Anak sama sekali.
JSX memiliki atribut sebaran API yang sering saya gunakan pada komponen seperti Child. Dibutuhkan semua
props
dan menerapkannya ke komponen. Anak akan terlihat seperti ini:Mengizinkan Anda menggunakan nilai langsung di Induk:
Snapshot JSBin
Dan tidak ada konfigurasi tambahan yang diperlukan saat Anda menghubungkan komponen Anak tambahan
Snapshot JSBin
Tapi saya menduga itu bukan kasus penggunaan Anda yang sebenarnya. Jadi mari kita menggali lebih jauh ...
Contoh praktis yang kuat
Sifat generik dari contoh yang diberikan sulit untuk dibicarakan. Saya telah membuat komponen yang menunjukkan penggunaan praktis untuk pertanyaan di atas, diimplementasikan dengan cara yang sangat Reacty :
DTServiceCalculator contoh kerja
repo DTServiceCalculator
Komponen ini adalah kalkulator layanan sederhana. Anda memberinya daftar layanan (dengan nama dan harga) dan itu akan menghitung total harga yang dipilih.
Anak-anak sangat bodoh
ServiceItem
adalah komponen anak dalam contoh ini. Itu tidak memiliki banyak pendapat tentang dunia luar. Dibutuhkan beberapa alat peraga , salah satunya adalah fungsi yang dipanggil ketika diklik.<div onClick={this.props.handleClick.bind(this.props.index)} />
Ia tidak melakukan apa-apa selain memanggil
handleClick
callback yang disediakan denganindex
[ sumber ] yang disediakan .Orang tua adalah anak-anak
DTServicesCalculator
adalah komponen induk adalah contoh ini. Itu juga anak-anak. Mari lihat.DTServiceCalculator
menciptakan daftar anak-komponen (ServiceItem
s) dan menyediakan mereka dengan alat peraga [ sumber ]. Ini adalah komponen indukServiceItem
tetapi komponen anak dari komponen yang meneruskannya daftar. Itu tidak memiliki data. Jadi sekali lagi ia mendelegasikan penanganan komponen ke sumber komponen induknya<ServiceItem chosen={chosen} index={i} key={id} price={price} name={name} onSelect={this.props.handleServiceItem} />
handleServiceItem
menangkap indeks, lulus dari anak, dan memberikannya kepada induknya [ sumber ]Pemilik tahu segalanya
Konsep "Kepemilikan" adalah yang penting dalam Bereaksi. Saya sarankan membaca lebih lanjut di sini .
Dalam contoh yang saya tunjukkan, saya terus mendelegasikan penanganan acara ke pohon komponen sampai kita sampai ke komponen yang memiliki keadaan.
Ketika kami akhirnya sampai di sana, kami menangani pemilihan / penghilangan status seperti seperti [ sumber ]:
Kesimpulan
Coba jaga agar komponen terluar Anda tidak tembus cahaya. Berusaha keras untuk memastikan bahwa mereka memiliki sangat sedikit preferensi tentang bagaimana komponen induk mungkin memilih untuk mengimplementasikannya.
Waspadai siapa yang memiliki data yang Anda manipulasi. Dalam kebanyakan kasus, Anda perlu mendelegasikan acara yang menangani pohon ke komponen yang memiliki status itu.
Selain: Pola fluks adalah cara yang baik untuk mengurangi jenis kaitan yang diperlukan dalam aplikasi.
sumber
Parent
mungkin seperti Controller-View, sementaraChild
itu hanya View-dumb (komponen). Hanya Controller-Views yang memiliki pengetahuan aplikasi. Dalam hal ini, Anda masih akan melewatkan Action dariParent
menjadiChild
sebagai penyangga. Terkait dengan Tindakan itu sendiri, Flux memiliki pola yang sangat ditentukan untuk berinteraksi antara Tindakan untuk memperbarui Tampilan. facebook.github.io/flux/docs/…onClick={this.onClick.bind(null, this.state.text)}
tidak perlu mengikat negara karena orang tua memilikinya. jadi hanyaonClick={this.onClick}
akan bekerja.onClick = ()=>{const text = this.state.text;..}
di mana pada orang tuaTampaknya ada jawaban sederhana. Pertimbangkan ini:
Kuncinya adalah memanggil
bind(null, this)
padathis.props.onClick
acara, lulus dari orangtua. Sekarang, fungsi onClick menerima argumencomponent
, DANevent
. Saya pikir itu yang terbaik dari semua dunia.UPDATE: 9/1/2015
Ini adalah ide yang buruk: membiarkan detail implementasi anak bocor ke orang tua tidak pernah jalan yang baik. Lihat jawaban Sebastien Lorber.
sumber
this
dalam fungsi (yang tidak diperlukan pula), dan argumen kedua adalah argumen pertama ketika onClick dipanggil.Pertanyaannya adalah bagaimana cara menyampaikan argumen dari komponen child ke parent. Contoh ini mudah digunakan dan diuji:
Lihatlah JSFIDDLE
sumber
Pada dasarnya Anda menggunakan alat peraga untuk mengirim informasi ke dan dari Anak dan Orang Tua.
Menambah semua jawaban yang bagus, izinkan saya memberikan contoh sederhana yang menjelaskan nilai-nilai yang diteruskan dari komponen child ke parent di React
App.js
Header.js
Main.js
Itu saja, sekarang Anda dapat meneruskan nilai dari klien Anda ke server.
Lihatlah fungsi Ubah di Header.js
Ini adalah bagaimana Anda mendorong nilai ke dalam alat peraga dari klien ke server
sumber
Berikut ini adalah implementasi ES6 3 langkah sederhana menggunakan fungsi binding di induk konstruktor. Ini adalah cara pertama yang direkomendasikan tutorial reaksi resmi (ada juga sintaks bidang kelas publik yang tidak dibahas di sini). Anda dapat menemukan semua informasi ini di sini https://reactjs.org/docs/handling-events.html
Mengikat Fungsi Induk sehingga Anak-Anak Dapat Memanggil Mereka (Dan meneruskan data ke orang tua!: D)
Fungsi Induk
Konstruktor Induk
Prop Disahkan ke Anak
Panggilan Acara Anak
sumber
Ini adalah contoh tanpa menggunakan acara onClick. Saya hanya memberikan fungsi panggilan balik kepada anak dengan alat peraga. Dengan panggilan balik itu, panggilan anak juga mengirim data kembali. Saya terinspirasi oleh contoh-contoh dalam dokumen .
Contoh kecil (ini ada dalam file tsx, jadi props dan state harus dideklarasikan sepenuhnya, saya menghapus beberapa logika dari komponen, jadi lebih sedikit kode).
* Pembaruan: Penting untuk mengikat ini ke callback, kalau tidak callback memiliki ruang lingkup anak dan bukan orang tua. Satu-satunya masalah: itu adalah orangtua "lama" ...
SymptomChoser adalah induknya:
Gejala adalah anak (dalam properti anak saya menyatakan fungsi panggilan balik, dalam fungsi yang dipilih. Gejala panggilan dipanggil):
sumber