Saya punya dua komponen.
- Komponen induk
- Komponen anak
Saya mencoba memanggil metode anak dari Orang Tua, saya mencoba cara ini tetapi tidak mendapatkan hasil
class Parent extends Component {
render() {
return (
<Child>
<button onClick={Child.getAlert()}>Click</button>
</Child>
);
}
}
class Child extends Component {
getAlert() {
alert('clicked');
}
render() {
return (
<h1 ref="hello">Hello</h1>
);
}
}
Apakah ada cara untuk memanggil metode anak dari orang tua?
Catatan: Komponen Anak dan Orang Tua ada dalam dua file berbeda
javascript
reactjs
N8FURY
sumber
sumber
Jawaban:
Pertama, izinkan saya menyatakan bahwa ini umumnya bukan cara untuk melakukan hal-hal di Bereaksi tanah. Biasanya yang ingin Anda lakukan adalah memberikan fungsi kepada anak-anak dalam alat peraga, dan meneruskan pemberitahuan dari anak-anak di acara (atau lebih baik lagi:)
dispatch
.Tetapi jika Anda harus mengekspos metode imperatif pada komponen anak, Anda dapat menggunakan referensi . Ingat ini adalah jalan keluar dan biasanya menunjukkan desain yang lebih baik tersedia.
Menggunakan Pengait dan Komponen Fungsi (
>= [email protected]
)Dokumentasi untuk
useImperativeHandle()
adalah di sini :Menggunakan Komponen Kelas (
>= [email protected]
)API Warisan (
<= [email protected]
)Untuk tujuan historis, inilah gaya berbasis panggilan balik yang akan Anda gunakan dengan React versi sebelum 16.3:
sumber
connect
mengembalikan komponen orde tinggi yang membungkus instance asli Anda. Anda harus memanggilgetWrappedInstance()
komponen yang terhubung terlebih dahulu untuk mendapatkan komponen asli Anda. Kemudian Anda dapat memanggil metode instan untuk itu.componentWillReceiveProps
, dan menggunakannya sebagai pemicu.Anda dapat menggunakan pola lain di sini:
Apa yang dilakukannya adalah mengatur metode induk
clickChild
ketika anak di-mount. Dengan cara ini ketika Anda mengklik tombol pada orang tua itu akan memanggil panggilanclickChild
mana yang anakgetAlert
.Ini juga berfungsi jika anak Anda dibungkus dengan
connect()
sehingga Anda tidak perlugetWrappedInstance()
meretas.Catatan Anda tidak dapat menggunakan
onClick={this.clickChild}
pada orang tua karena ketika orang tua diberikan anak tidak dipasang sehinggathis.clickChild
belum ditugaskan. PenggunaannyaonClick={() => this.clickChild()}
baik-baik saja karena ketika Anda mengklik tombolthis.clickChild
sudah harus ditugaskan.sumber
_this2.clickChild is not a function
mengapa?https://facebook.github.io/react/tips/expose-component-functions.html untuk jawaban lebih lanjut ada di sini Metode panggilan pada komponen React children
Dengan melihat referensi komponen "alasan", Anda memecahkan enkapsulasi dan membuatnya tidak mungkin untuk memperbaiki komponen itu tanpa memeriksa dengan cermat semua tempat yang digunakan. Karena itu, kami sangat menyarankan memperlakukan ref sebagai komponen pribadi, seperti halnya negara.
Secara umum, data harus diturunkan pohon melalui alat peraga. Ada beberapa pengecualian untuk ini (seperti memanggil .focus () atau memicu animasi satu kali yang tidak benar-benar "mengubah" keadaan) tetapi setiap kali Anda mengekspos metode yang disebut "set", alat peraga biasanya pilihan yang lebih baik. Cobalah membuatnya sehingga komponen input dalam khawatir tentang ukuran dan penampilannya sehingga tidak ada leluhurnya yang melakukannya.
sumber
Metode alternatif dengan useEffect:
Induk:
Anak-anak:
sumber
Kita bisa menggunakan referensi dengan cara lain seperti-
Kami akan membuat elemen Induk, itu akan membuat
<Child/>
komponen. Seperti yang Anda lihat, komponen yang akan di-render, Anda perlu menambahkan atribut ref dan memberikan nama untuknya.Kemudian,
triggerChildAlert
fungsi, yang terletak di kelas induk akan mengakses properti referensi konteks ini (ketikatriggerChildAlert
fungsi dipicu akan mengakses referensi anak dan itu akan memiliki semua fungsi elemen anak).Sekarang, komponen anak, seperti yang dirancang secara teoritis sebelumnya, akan terlihat seperti:
Berikut adalah kode sumber -
Harapan akan membantu Anda!
sumber
Jika Anda melakukan ini hanya karena Anda ingin Anak memberikan sifat yang dapat digunakan kembali kepada orang tuanya, maka Anda dapat mempertimbangkan melakukan itu menggunakan render-props sebagai gantinya.
Teknik itu sebenarnya membalikkan struktur. The
Child
sekarang membungkus orang tua, jadi saya telah berganti nama keAlertTrait
bawah. Saya menjaga namaParent
untuk kesinambungan, meskipun sekarang ini bukan orang tua.Dalam hal ini, AlertTrait menyediakan satu atau beberapa sifat yang dilewatkan sebagai
renderComponent
penyangga ke komponen apa pun yang diberikan pada penyangga.Orangtua menerima
doAlert
sebagai alat peraga, dan dapat memanggilnya saat dibutuhkan.(Untuk lebih jelasnya, saya menyebut prop
renderComponent
dalam contoh di atas. Tetapi dalam React docs yang ditautkan di atas, mereka menyebutnya begiturender
.)Komponen Trait dapat membuat hal-hal di sekitar Induk, dalam fungsi rendernya, tetapi tidak membuat apa pun di dalam induk. Sebenarnya itu bisa membuat hal-hal di dalam Induk, jika melewati prop lain (mis
renderChild
) kepada orangtua, yang kemudian dapat digunakan orangtua selama metode rendernya.Ini agak berbeda dari apa yang diminta OP, tetapi beberapa orang mungkin berakhir di sini (seperti yang kita lakukan) karena mereka ingin membuat sifat yang dapat digunakan kembali, dan berpikir bahwa komponen anak adalah cara yang baik untuk melakukan itu.
sumber
this.clickChild = click
tetapi beberapa stopwatch Anda akan melewati beberapa fungsi, jadi Anda harus menyimpan semuanya:this.watchRestartFuncs[watchId] = restartWatch
Anda dapat mencapai ini dengan mudah dengan cara ini
Langkah-
Dari komponen anak akses variabel itu menggunakan alat peraga dan jalankan metode yang Anda inginkan dengan memiliki kondisi if.
sumber
Saya menggunakan
useEffect
kait untuk mengatasi sakit kepala melakukan semua ini jadi sekarang saya meneruskan variabel ke anak seperti ini:sumber
Saya tidak puas dengan solusi yang disajikan di sini. Sebenarnya ada solusi yang sangat sederhana yang dapat dilakukan menggunakan Javascript murni tanpa mengandalkan beberapa fungsi Bereaksi selain objek alat peraga dasar - dan itu memberi Anda manfaat berkomunikasi di kedua arah (induk -> anak, anak -> orangtua). Anda perlu meneruskan objek dari komponen induk ke komponen turunan. Objek ini adalah apa yang saya sebut sebagai "referensi dua arah" atau singkatnya biRef. Pada dasarnya, objek berisi referensi ke metode pada induk yang ingin diekspos oleh induk. Dan komponen anak melampirkan metode ke objek yang dapat dipanggil orang tua. Sesuatu seperti ini:
Keuntungan lain dari solusi ini adalah Anda dapat menambahkan lebih banyak fungsi di induk dan anak sambil meneruskannya dari induk ke anak dengan hanya menggunakan satu properti.
Peningkatan atas kode di atas adalah untuk tidak menambahkan fungsi induk dan anak secara langsung ke objek biRef melainkan ke sub anggota. Fungsi induk harus ditambahkan ke anggota yang disebut "induk" sedangkan fungsi anak harus ditambahkan ke anggota yang disebut "anak".
Dengan menempatkan fungsi orangtua dan anak ke dalam anggota yang terpisah dari objek biRef, Anda akan memiliki pemisahan yang bersih antara keduanya dan dengan mudah melihat mana yang milik orangtua atau anak. Ini juga membantu mencegah komponen anak dari menimpa fungsi orangtua secara tidak sengaja jika fungsi yang sama muncul di keduanya.
Satu hal terakhir adalah bahwa jika Anda perhatikan, komponen induk membuat objek biRef dengan var sedangkan komponen anak mengaksesnya melalui objek props. Mungkin tergoda untuk tidak mendefinisikan objek biRef di induk dan mengaksesnya dari induknya melalui parameter propsnya sendiri (yang mungkin merupakan kasus dalam hierarki elemen UI). Ini berisiko karena anak mungkin berpikir suatu fungsi yang dipanggilnya pada orangtua adalah milik orangtua padahal sebenarnya itu milik kakek-nenek. Tidak ada yang salah dengan ini selama Anda menyadarinya. Kecuali Anda memiliki alasan untuk mendukung beberapa hierarki di luar hubungan orang tua / anak, yang terbaik adalah membuat biRef di komponen induk Anda.
sumber
Anda dapat membuat Inheritance Inversion (lihat di sini: https://medium.com/@franleplant/react-higher-order-components-in-depth-cf9032ee6c3e ). Dengan begitu Anda memiliki akses ke instance komponen yang akan Anda bungkus (sehingga Anda akan dapat mengakses fungsinya)
sumber
Saya pikir cara paling dasar untuk memanggil metode adalah dengan menetapkan permintaan pada komponen anak. Kemudian segera setelah anak menangani permintaan, ia memanggil metode panggilan balik untuk mereset permintaan.
Mekanisme reset diperlukan untuk dapat mengirim permintaan yang sama beberapa kali setelah satu sama lain.
Dalam komponen induk
Dalam metode render dari induk:
Orang tua membutuhkan 2 metode, untuk berkomunikasi dengan anaknya dalam 2 arah.
Dalam komponen anak
Anak itu memperbarui keadaan internalnya, menyalin permintaan dari alat peraga.
Lalu akhirnya ia menangani permintaan, dan mengirimkan reset ke induk:
sumber
Cara lain untuk memicu fungsi anak dari orang tua adalah dengan memanfaatkan
componentDidUpdate
fungsi dalam Komponen anak. Saya melewati proptriggerChildFunc
dari Parent to Child, yang awalnya adalahnull
. Nilai berubah menjadi fungsi ketika tombol diklik dan Anak melihat bahwa perubahancomponentDidUpdate
dan memanggil fungsi internalnya sendiri.Karena prop
triggerChildFunc
berubah ke fungsi, kami juga menerima panggilan balik ke Induk. Jika Induk tidak perlu tahu kapan fungsi dipanggil nilaitriggerChildFunc
misalnya bisa berubah darinull
menjaditrue
.CodePen: https://codepen.io/calsal/pen/NWPxbJv?editors=1010
sumber
Di sini, demo saya: https://stackblitz.com/edit/react-dgz1ee?file=styles.css
Saya menggunakan
useEffect
untuk memanggil metode komponen anak-anak. Saya sudah mencobaProxy and Setter_Getter
tetapiuseEffect
tampaknya jauh lebih mudah untuk memanggil metode anak dari orang tua. Untuk menggunakannyaProxy and Setter_Getter
sepertinya ada beberapa kehalusan untuk diatasi terlebih dahulu, karena elemen yang pertama kali diberikan adalah elemen objectLike melaluiref.current return => <div/>
spesifisitas. MengenaiuseEffect
, Anda juga dapat memanfaatkan pendekatan ini untuk mengatur keadaan orang tua tergantung pada apa yang ingin Anda lakukan dengan anak-anak.Di tautan demo yang saya berikan, Anda akan menemukan kode ReactJS saya lengkap dengan konsep saya di dalam sehingga Anda dapat menghargai alur kerja solusi saya.
Di sini saya memberi Anda hanya potongan kode ReactJS saya yang relevan. :
sumber
Kami senang dengan kait khusus yang kami sebut
useCounterKey
. Itu hanya membuat counterKey, atau kunci yang dihitung dari nol. Fungsi yang dikembalikan mengembalikan kunci (mis. Kenaikan). (Saya percaya ini adalah cara paling idiomatis dalam Bereaksi untuk mereset komponen - cukup tekan tombol.)Namun kait ini juga berfungsi dalam situasi apa pun di mana Anda ingin mengirim pesan satu kali kepada klien untuk melakukan sesuatu. Misalnya kita menggunakannya untuk memfokuskan kontrol pada anak pada acara induk tertentu - itu hanya fokus otomatis kapan saja kunci diperbarui. (Jika lebih banyak alat peraga diperlukan, mereka dapat diatur sebelum mengatur ulang kunci sehingga tersedia saat acara terjadi.)
Metode ini memiliki sedikit kurva belajar b / c tidak semudah penanganan kejadian biasa, tetapi tampaknya cara yang paling idiomatis untuk menangani ini dalam Bereaksi yang kami temukan (karena kunci sudah berfungsi dengan cara ini). Def terbuka untuk umpan balik tentang metode ini tetapi itu bekerja dengan baik!
Penggunaan sampel:
(Kredit untuk Kent Dodds untuk konsep kontraKey .)
sumber
Ini bugnya? yang harus diwaspadai: Saya setuju dengan solusi rossipedia menggunakan forwardRef, useRef, useImperativeHandle
Ada beberapa informasi yang salah di internet yang mengatakan bahwa referensi hanya dapat dibuat dari komponen React Class, tetapi Anda memang dapat menggunakan Komponen Fungsi jika Anda menggunakan kait yang disebutkan di atas. Catatan, kait hanya berfungsi untuk saya setelah saya mengubah file untuk tidak menggunakan withRouter () saat mengekspor komponen. Yaitu perubahan dari
untuk menjadi
Di belakang withRouter () tidak diperlukan untuk komponen seperti itu, tapi biasanya tidak ada salahnya masuk. Kasus penggunaan saya adalah saya membuat komponen untuk membuat Tabel untuk menangani tampilan dan pengeditan nilai konfigurasi, dan saya ingin dapat memberi tahu komponen Child ini untuk mereset nilai-nilai keadaannya setiap kali tombol Reset formulir Induk ditekan. UseRef () tidak akan mendapatkan ref atau ref.current dengan benar (terus menjadi nol) sampai saya dihapus denganRouter () dari file yang mengandung komponen anak saya TableConfig
sumber