Pass props ke komponen induk di React.js

295

Apakah tidak ada cara sederhana untuk mengirimkan anak propske 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.

KendallB
sumber
Ada berbagai jawaban untuk masalah yang sama (di sini dan di sini ), tetapi tidak satupun dari mereka yang tampak sangat elegan
Bojangles
Saya setuju - melewatkan acara di atas rantai itu bagus, tetapi akan luar biasa untuk mengetahui dengan pasti komponen mana yang memulai acara tersebut.
KendallB
Silakan lihat jawaban saya, karena saya pikir jawaban yang diterima tidak cukup baik; stackoverflow.com/a/31756470/82609
Sebastien Lorber
1
kit n 'kaboodle - Untuk memasukkan semuanya. Untuk mendapatkan semua lonceng dan peluit. Combonation. urbandictionary.com/define.php?term=kit%20and%20caboodle
Filip Bartuzi

Jawaban:

268

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.

Apakah tidak ada cara sederhana untuk meneruskan alat peraga anak ke orang tuanya menggunakan acara, di React.js?

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.

var Child = React.createClass({
  render: function () {
    return <button onClick={this.props.onClick}>{this.props.text}</button>;
  },
});

Orang tua dengan anak tunggal : menggunakan nilai yang diberikan kepada anak

var Parent = React.createClass({
  getInitialState: function() {
     return {childText: "Click me! (parent prop)"};
  },
  render: function () {
    return (
      <Child onClick={this.handleChildClick} text={this.state.childText}/>
    );
  },
  handleChildClick: function(event) {
     // You can access the prop you pass to the children 
     // because you already have it! 
     // Here you have it in state but it could also be
     //  in props, coming from another parent.
     alert("The Child button text is: " + this.state.childText);
     // You can also access the target of the click here 
     // if you want to do some magic stuff
     alert("The Child HTML is: " + event.target.outerHTML);
  }
});

JsFiddle

Orangtua dengan daftar anak : Anda masih memiliki semua yang Anda butuhkan pada orang tua dan tidak perlu membuat anak lebih rumit.

var Parent = React.createClass({
  getInitialState: function() {
     return {childrenData: [
         {childText: "Click me 1!", childNumber: 1},
         {childText: "Click me 2!", childNumber: 2}
     ]};
  },
  render: function () {
    var children = this.state.childrenData.map(function(childData,childIndex) {
        return <Child onClick={this.handleChildClick.bind(null,childData)} text={childData.childText}/>;
    }.bind(this));
    return <div>{children}</div>;
  },

  handleChildClick: function(childData,event) {
     alert("The Child button data is: " + childData.childText + " - " + childData.childNumber);
     alert("The Child HTML is: " + event.target.outerHTML);
  }
});

JsFiddle

Dimungkinkan juga untuk digunakan this.handleChildClick.bind(null,childIndex)dan kemudian digunakanthis.state.childrenData[childIndex]

Catatan kami mengikat dengan nullkonteks 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:

var Parent = React.createClass({
  handleClick: function(childComponent) {
     // using childComponent.props
     // using childComponent.refs.button
     // or anything else using childComponent
  },
  render: function() {
    <Child onClick={this.handleClick} />
  }
});

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:

<Child ref="theChild" .../>

Dan akses simpul DOM di induk dengan

React.findDOMNode(this.refs.theChild)

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 ...:

Mereka menciptakan batas antara apa yang Anda, pengembang Web dapat capai dan apa yang dianggap detail implementasi, sehingga tidak dapat diakses oleh Anda. Namun browser, dapat melintasi batas ini sesuka hati. Dengan batas ini di tempat, mereka dapat membangun semua elemen HTML menggunakan teknologi Web lama yang sama, dari div dan bentang seperti yang Anda inginkan.

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(...)atau childComponent.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:

const Child = ({
  onClick, 
  text
}) => (
  <button onClick={onClick}>
    {text}
  </button>
)

Orang tua dapat berupa kelas (dan akhirnya dapat mengelola negara itu sendiri, tapi saya meneruskannya sebagai alat peraga di sini:

class Parent1 extends React.Component {
  handleChildClick(childData,event) {
     alert("The Child button data is: " + childData.childText + " - " + childData.childNumber);
     alert("The Child HTML is: " + event.target.outerHTML);
  }
  render() {
    return (
      <div>
        {this.props.childrenData.map(child => (
          <Child
            key={child.childNumber}
            text={child.childText} 
            onClick={e => this.handleChildClick(child,e)}
          />
        ))}
      </div>
    );
  }
}

Tetapi ini juga dapat disederhanakan jika tidak perlu mengatur status:

const Parent2 = ({childrenData}) => (
  <div>
     {childrenData.map(child => (
       <Child
         key={child.childNumber}
         text={child.childText} 
         onClick={e => {
            alert("The Child button data is: " + child.childText + " - " + child.childNumber);
                    alert("The Child HTML is: " + e.target.outerHTML);
         }}
       />
     ))}
  </div>
)

JsFiddle


PERF PERINGATAN (berlaku untuk ES5 / ES6): jika Anda menggunakan PureComponentatau shouldComponentUpdate, implementasi di atas tidak akan dioptimalkan secara default karena menggunakan onClick={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 ke thisdalam konstruktor kelas) sehingga PureComponentoptimisasi dapat dimulai, atau Anda dapat menerapkan sendiri shouldComponentUpdatedan 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:

// A component that is expensive to render
const ExpensiveComponent = ({ propA, propB }) => {...}

// Optimized version of same component, using shallow comparison of props
// Same effect as React's PureRenderMixin
const OptimizedComponent = pure(ExpensiveComponent)

// Even more optimized: only updates if specific prop keys have changed
const HyperOptimizedComponent = onlyUpdateForKeys(['propA', 'propB'])(ExpensiveComponent)

Dalam hal ini Anda dapat mengoptimalkan komponen Anak dengan menggunakan:

const OptimizedChild = onlyUpdateForKeys(['text'])(Child)
Sebastien Lorber
sumber
1
Ya, setelah menghabiskan tahun terakhir menggunakan Bereaksi, saya setuju - tidak ada alasan yang baik untuk melewati komponen instantiated sekitar melalui fungsi. Saya akan mencela jawaban saya sendiri. Saya juga bersedia mengganti jawabannya, mungkin dengan beberapa modifikasi: "Implementasi Anda yang lebih baik" tidak menjawab alasan sebenarnya pertanyaan ini muncul, yaitu, "Bagaimana saya tahu anak-anak saya mana yang dipilih di antara suatu kelompok?" Flux adalah jawaban untuk semua aplikasi berukuran layak, namun, dalam aplikasi kecil saya senang untuk meneruskan nilai (bukan komponen) mencadangkan rantai panggilan melalui fungsi aktif props. Setuju?
KendallB
@ KendallB senang Anda setuju dengan jawaban saya :) 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 gunakan bindlangsung di induknya.
Sebastien Lorber
Saya mengedit jawaban Anda, bagian tentang referensi. omerwazir.com/posts/react-getdomnode-replaced-with-findDOMNode
ffxsam
Hai @SebastienLorber Saya datang dari masa depan. Mengenai baris ini yang 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 ES6 class modelomong-omong, jadi aku berubah nullke thisdan kode saya tampaknya masih bekerja. Bagaimana Anda menerjemahkan bagian kode Anda menjadi gaya ES6?
JohnnyQ
Saya juga berjuang agar ini berfungsi dalam React terbaru, apa yang perlu diubah?
Hussein Duvigneau
143

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 onClickmenjadi this.props.onClick.bind(null, this):

var Child = React.createClass({
  render: function () {
    return <a onClick={this.props.onClick.bind(null, this)}>Click me</a>;
  }
});

Penangan acara di Induk Anda kemudian dapat mengakses komponen dan acara seperti:

  onClick: function (component, event) {
    // console.log(component, event);
  },

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:

var Child = React.createClass({
  render: function () {
    return <a onClick={this.props.onClick}> {this.props.text} </a>;
  }
});

var Parent = React.createClass({
  getInitialState: function () {
    return { text: "Click here" };
  },
  onClick: function (event) {
    // event.component.props ?why is this not available? 
  },
  render: function() {
    return <Child onClick={this.onClick} text={this.state.text} />;
  }
});

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 propsdan menerapkannya ke komponen. Anak akan terlihat seperti ini:

var Child = React.createClass({
  render: function () {
    return <a {...this.props}> {this.props.text} </a>;
  }
});

Mengizinkan Anda menggunakan nilai langsung di Induk:

var Parent = React.createClass({
  getInitialState: function () {
    return { text: "Click here" };
  },
  onClick: function (text) {
    alert(text);
  },
  render: function() {
    return <Child onClick={this.onClick.bind(null, this.state.text)} text={this.state.text} />;
  }
});

Snapshot JSBin


Dan tidak ada konfigurasi tambahan yang diperlukan saat Anda menghubungkan komponen Anak tambahan

var Parent = React.createClass({
  getInitialState: function () {
    return {
      text: "Click here",
      text2: "No, Click here",
    };
  },
  onClick: function (text) {
    alert(text);
  },
  render: function() {
    return <div>
      <Child onClick={this.onClick.bind(null, this.state.text)} text={this.state.text} />
      <Child onClick={this.onClick.bind(null, this.state.text2)} text={this.state.text2} />
    </div>;
  }
});

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

ServiceItemadalah 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 handleClickcallback yang disediakan dengan index[ sumber ] yang disediakan .

Orang tua adalah anak-anak

DTServicesCalculatoradalah komponen induk adalah contoh ini. Itu juga anak-anak. Mari lihat.

DTServiceCalculatormenciptakan daftar anak-komponen ( ServiceItems) dan menyediakan mereka dengan alat peraga [ sumber ]. Ini adalah komponen induk ServiceItemtetapi 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} />

handleServiceItemmenangkap indeks, lulus dari anak, dan memberikannya kepada induknya [ sumber ]

handleServiceClick (index) {
  this.props.onSelect(index);
}

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 ]:

handleSelect (index) {
  let services = […this.state.services];
  services[index].chosen = (services[index].chosen) ? false : true;
  this.setState({ services: services });
}


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.

chantastic
sumber
Terima kasih atas jawaban singkatnya, sangat membantu saya memahami Bereaksi sedikit lebih baik! Saya punya pertanyaan di sepanjang baris yang sama. Saya menggunakan Flux untuk pub / sub. Alih-alih menyerahkan pengendali acara Anak ke Orang Tua seperti contoh Anda, mungkin untuk menerapkan ini sebagai 'tindakan' dan dengarkan itu. Apakah Anda menganggap ini alternatif yang baik dan penggunaan Flux?
Pathsofdesign
1
Terima kasih @Pathsofdesign! Itu akan tergantung. Flux memiliki konsep Controller-Views ini. Dalam contoh ini, Parentmungkin seperti Controller-View, sementara Childitu hanya View-dumb (komponen). Hanya Controller-Views yang memiliki pengetahuan aplikasi. Dalam hal ini, Anda masih akan melewatkan Action dariParent menjadi Childsebagai penyangga. Terkait dengan Tindakan itu sendiri, Flux memiliki pola yang sangat ditentukan untuk berinteraksi antara Tindakan untuk memperbarui Tampilan. facebook.github.io/flux/docs/…
chantastic
1
onClick={this.onClick.bind(null, this.state.text)}tidak perlu mengikat negara karena orang tua memilikinya. jadi hanya onClick={this.onClick}akan bekerja. onClick = ()=>{const text = this.state.text;..}di mana pada orang tua
Shishir Arora
25

Tampaknya ada jawaban sederhana. Pertimbangkan ini:

var Child = React.createClass({
  render: function() {
    <a onClick={this.props.onClick.bind(null, this)}>Click me</a>
  }
});

var Parent = React.createClass({
  onClick: function(component, event) {
    component.props // #=> {Object...}
  },
  render: function() {
    <Child onClick={this.onClick} />
  }
});

Kuncinya adalah memanggil bind(null, this)pada this.props.onClickacara, lulus dari orangtua. Sekarang, fungsi onClick menerima argumen component, DAN event. 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.

KendallB
sumber
bukankah argumennya salah (tempat bertukar)?
The Surrican
1
@TheSurrican Tidak, tidak apa-apa. Argumen pertama terikat ke thisdalam fungsi (yang tidak diperlukan pula), dan argumen kedua adalah argumen pertama ketika onClick dipanggil.
manmal
13

Pertanyaannya adalah bagaimana cara menyampaikan argumen dari komponen child ke parent. Contoh ini mudah digunakan dan diuji:

//Child component
class Child extends React.Component {
    render() {
        var handleToUpdate  =   this.props.handleToUpdate;
        return (<div><button onClick={() => handleToUpdate('someVar')}>Push me</button></div>
        )
    }
}

//Parent component
class Parent extends React.Component {
    constructor(props) {
        super(props);
        var handleToUpdate  = this.handleToUpdate.bind(this);
    }

    handleToUpdate(someArg){
        alert('We pass argument from Child to Parent: \n' + someArg);
    }

    render() {
        var handleToUpdate  =   this.handleToUpdate;
        return (<div>
          <Child handleToUpdate = {handleToUpdate.bind(this)} />
        </div>)
    }
}

if(document.querySelector("#demo")){
    ReactDOM.render(
        <Parent />,
        document.querySelector("#demo")
    );
}

Lihatlah JSFIDDLE

Roma
sumber
Dalam kasus saya itu lupa melewati fungsi callback ke klik ()
Long Nguyen
6

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

class App extends React.Component {
      constructor(){
            super();
            this.handleFilterUpdate = this.handleFilterUpdate.bind(this);
            this.state={name:'igi'}
      }
      handleFilterUpdate(filterValue) {
            this.setState({
                  name: filterValue
            });
      }
   render() {
      return (
        <div>
            <Header change={this.handleFilterUpdate} name={this.state.name} />
            <p>{this.state.name}</p>
        </div>
      );
   }
}

Header.js

class Header extends React.Component {
      constructor(){
            super();
            this.state={
                  names: 'jessy'
            }
      }
      Change(event) {

      // this.props.change(this.state.names);
      this.props.change('jessy');
  }

   render() {
      return (
       <button onClick={this.Change.bind(this)}>click</button>

      );
   }
}

Main.js

import React from 'react';
import ReactDOM from 'react-dom';

import App from './App.jsx';

ReactDOM.render(<App />, document.getElementById('app'));

Itu saja, sekarang Anda dapat meneruskan nilai dari klien Anda ke server.

Lihatlah fungsi Ubah di Header.js

Change(event) {
      // this.props.change(this.state.names);
      this.props.change('jessy');
  }

Ini adalah bagaimana Anda mendorong nilai ke dalam alat peraga dari klien ke server

Ignatius Andrew
sumber
Bolehkah saya tahu Ini adalah bagaimana Anda mendorong nilai ke dalam alat peraga dari klien ke server, apa yang Anda maksud dengan pernyataan ini
G1P
2

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)

  1. Pastikan di konstruktor induk Anda mengikat fungsi yang Anda buat di induk
  2. Berikan fungsi terikat ke anak sebagai penyangga (Tidak lambda karena kami memberikan referensi untuk berfungsi)
  3. Panggil fungsi terikat dari acara anak (Lambda! Kami memanggil fungsi ketika acara dipecat. Jika kami tidak melakukan ini fungsi akan secara otomatis berjalan pada beban dan tidak dipicu pada acara tersebut.)

Fungsi Induk

handleFilterApply(filterVals){} 

Konstruktor Induk

this.handleFilterApply = this.handleFilterApply.bind(this);

Prop Disahkan ke Anak

onApplyClick = {this.handleFilterApply}

Panggilan Acara Anak

onClick = {() => {props.onApplyClick(filterVals)}
Jordan H
sumber
0

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:

interface SymptomChooserState {
  // true when a symptom was pressed can now add more detail
  isInDetailMode: boolean
  // since when user has this symptoms
  sinceDate: Date,
}

class SymptomChooser extends Component<{}, SymptomChooserState> {

  state = {
    isInDetailMode: false,
    sinceDate: new Date()
  }

  helloParent(symptom: Symptom) {
    console.log("This is parent of: ", symptom.props.name);
    // TODO enable detail mode
  }

  render() {
    return (
      <View>
        <Symptom name='Fieber' callback={this.helloParent.bind(this)} />
      </View>
    );
  }
}

Gejala adalah anak (dalam properti anak saya menyatakan fungsi panggilan balik, dalam fungsi yang dipilih. Gejala panggilan dipanggil):

interface SymptomProps {
  // name of the symptom
  name: string,
  // callback to notify SymptomChooser about selected Symptom.
  callback: (symptom: Symptom) => void
}

class Symptom extends Component<SymptomProps, SymptomState>{

  state = {
    isSelected: false,
    severity: 0
  }

  selectedSymptom() {
    this.setState({ isSelected: true });
    this.props.callback(this);
  }

  render() {
    return (
      // symptom is not selected
      <Button
        style={[AppStyle.button]}
        onPress={this.selectedSymptom.bind(this)}>
        <Text style={[AppStyle.textButton]}>{this.props.name}</Text>
      </Button>
    );
  }
}
drewjosh
sumber