Bagaimana cara mengirimkan data dari komponen anak ke induknya di ReactJS?

212

Saya mencoba mengirim data dari komponen anak ke induknya sebagai berikut:

const ParentComponent = React.createClass({
    getInitialState() {
        return {
            language: '',
        };
    },
    handleLanguageCode: function(langValue) {
        this.setState({language: langValue});
    },

    render() {
         return (
                <div className="col-sm-9" >
                    <SelectLanguage onSelectLanguage={this.handleLanguage}/> 
                </div>
        );
});

dan di sini adalah komponen anak:

export const SelectLanguage = React.createClass({
    getInitialState: function(){
        return{
            selectedCode: '',
            selectedLanguage: '',
        };
    },

    handleLangChange: function (e) {
        var lang = this.state.selectedLanguage;
        var code = this.state.selectedCode;
        this.props.onSelectLanguage({selectedLanguage: lang});   
        this.props.onSelectLanguage({selectedCode: code});           
    },

    render() {
        var json = require("json!../languages.json");
        var jsonArray = json.languages;
        return (
            <div >
                <DropdownList ref='dropdown'
                    data={jsonArray} 
                    value={this.state.selectedLanguage}
                    caseSensitive={false} 
                    minLength={3}
                    filter='contains'
                    onChange={this.handleLangChange} />
            </div>            
        );
    }
});

Yang saya butuhkan adalah untuk mendapatkan nilai yang dipilih oleh pengguna di komponen induk. Saya mendapatkan kesalahan ini:

Uncaught TypeError: this.props.onSelectLanguage is not a function

Adakah yang bisa membantu saya menemukan masalahnya?

PS Komponen anak membuat dropdown dari file json, dan saya perlu daftar dropdown untuk menunjukkan kedua elemen array json di samping satu sama lain (seperti: "aaa, bahasa Inggris" sebagai pilihan pertama!)

{  
   "languages":[  
      [  
         "aaa",
         "english"
      ],
      [  
         "aab",
         "swedish"
      ],
}
Birish
sumber
3
<SelectLanguage onSelectLanguage={this.handleLanguage*Code*}/> salah ketik.
Yury Tarabanko
@YuryTarabanko Terima kasih, tetapi masih mendapatkan kesalahan yang sama
Birish
@DavinTryon Bagaimana saya harus menambahkannya? Saya mencoba seperti ini: handleLanguageCode: function(langValue) { this.setState({ language: langValue }).bind(this); },Tetapi mengembalikan kesalahan:ncaught TypeError: Cannot read property 'bind' of undefined
Birish
2
@DavinTryon createClassautobinds metode tidak bereaksi.
Yury Tarabanko
@OP, bisakah Anda membuat biola yang menunjukkan masalah?
Yury Tarabanko

Jawaban:

259

Ini seharusnya bekerja. Saat mengirim penyangga kembali, Anda mengirimnya sebagai objek, bukan mengirimnya sebagai nilai atau menggunakannya sebagai objek dalam komponen induk. Kedua Anda perlu memformat objek json Anda untuk memuat pasangan nilai nama dan penggunaan valueFieldserta textFieldatributDropdownList

Jawaban singkat

Induk:

<div className="col-sm-9">
     <SelectLanguage onSelectLanguage={this.handleLanguage} /> 
</div>

Anak:

handleLangChange = () => {
    var lang = this.dropdown.value;
    this.props.onSelectLanguage(lang);            
}

Terperinci:

EDIT:

Mempertimbangkan React.createClass sudah usang dari v16.0 dan seterusnya, Lebih baik untuk terus maju dan membuat Komponen Bereaksi dengan memperluas React.Component. Melewati data dari komponen child ke parent dengan sintaks ini akan terlihat seperti

Induk

class ParentComponent extends React.Component {

    state = { language: '' }

    handleLanguage = (langValue) => {
        this.setState({language: langValue});
    }

    render() {
         return (
                <div className="col-sm-9">
                    <SelectLanguage onSelectLanguage={this.handleLanguage} /> 
                </div>
        )
     }
}

Anak

var json = require("json!../languages.json");
var jsonArray = json.languages;

export class SelectLanguage extends React.Component {
    state = {
            selectedCode: '',
            selectedLanguage: jsonArray[0],
        }

    handleLangChange = () => {
        var lang = this.dropdown.value;
        this.props.onSelectLanguage(lang);            
    }

    render() {
        return (
            <div>
                <DropdownList ref={(ref) => this.dropdown = ref}
                    data={jsonArray} 
                    valueField='lang' textField='lang'
                    caseSensitive={false} 
                    minLength={3}
                    filter='contains'
                    onChange={this.handleLangChange} />
            </div>            
        );
    }
}

Menggunakan createClasssintaks yang digunakan OP dalam Parent jawabannya

const ParentComponent = React.createClass({
    getInitialState() {
        return {
            language: '',
        };
    },

    handleLanguage: function(langValue) {
        this.setState({language: langValue});
    },

    render() {
         return (
                <div className="col-sm-9">
                    <SelectLanguage onSelectLanguage={this.handleLanguage} /> 
                </div>
        );
});

Anak

var json = require("json!../languages.json");
var jsonArray = json.languages;

export const SelectLanguage = React.createClass({
    getInitialState: function() {
        return {
            selectedCode: '',
            selectedLanguage: jsonArray[0],
        };
    },

    handleLangChange: function () {
        var lang = this.refs.dropdown.value;
        this.props.onSelectLanguage(lang);            
    },

    render() {

        return (
            <div>
                <DropdownList ref='dropdown'
                    data={jsonArray} 
                    valueField='lang' textField='lang'
                    caseSensitive={false} 
                    minLength={3}
                    filter='contains'
                    onChange={this.handleLangChange} />
            </div>            
        );
    }
});

JSON:

{ 
"languages":[ 

    { 
    "code": "aaa", 
    "lang": "english" 
    }, 
    { 
    "code": "aab", 
    "lang": "Swedish" 
    }, 
  ] 
}
Shubham Khatri
sumber
Terima kasih Shubham, jawaban Anda memperbaiki masalah ini, tetapi tidak menunjukkan item yang dipilih di daftar turun bawah. Kosong setelah itu: /
Birish
@Sarah Saat membuat dropDownList Anda menetapkan nilainya sebagai this.state.selectedLanguage dan yang tidak diinisialisasi ke nilai apa pun. Mungkin itu masalahnya. Komponen DropdownList mana yang Anda gunakan. Jika saya tahu mungkin saya bisa mengatasinya untuk menyelesaikan masalah.
Shubham Khatri
Kamu benar. The this.state.selectedLanguagetampaknya selalu nol: / Saya menggunakan DropDownList darireact-widgets
Birish
@ Sarah Saya telah membuat sedikit perubahan pada kode, termasuk pengikatan nilai ke fungsi onChange dan menetapkan nilai status awal. Coba ini dan beri tahu saya jika itu berhasil untuk Anda
Shubham Khatri
Mengembalikan kesalahan: Uncaught ReferenceError: value is not defined. Saya membuat perubahan ini: onChange={this.handleLangChange.bind(this, this.value)}dan tidak ada kesalahan yang kembali, tetapi tetap saja tidak menunjukkan nilai yang dipilih :(
Birish
108

Untuk meneruskan data dari komponen anak ke komponen induk

Dalam Komponen Induk:

getData(val){
    // do not forget to bind getData in constructor
    console.log(val);
}
render(){
 return(<Child sendData={this.getData}/>);
}

Dalam Komponen Anak:

demoMethod(){
   this.props.sendData(value);
 }
Manisha Tan
sumber
15
Jangan lupa this.getData = this.getData.bind(this);di konstruktor, karena Anda mungkin mendapatkan this.setState bukan fungsi jika Anda ingin memanipulasi keadaan di getData.
Miro J.
12

Saya menemukan pendekatan bagaimana cara mendapatkan data dari komponen anak pada orang tua ketika saya membutuhkannya.

Induk:

class ParentComponent extends Component{
  onSubmit(data) {
    let mapPoint = this.getMapPoint();
  }

  render(){
    return (
      <form onSubmit={this.onSubmit.bind(this)}>
        <ChildComponent getCurrentPoint={getMapPoint => {this.getMapPoint = getMapPoint}} />
        <input type="submit" value="Submit" />
      </form>
    )
  }
}

Anak:

class ChildComponent extends Component{
  constructor(props){
    super(props);

    if (props.getCurrentPoint){
      props.getCurrentPoint(this.getMapPoint.bind(this));
    }
  }

  getMapPoint(){
    return this.Point;
  }
}

Contoh ini menunjukkan cara meneruskan fungsi dari komponen anak ke orang tua dan menggunakan fungsi ini untuk mendapatkan data dari anak.

MrDuDuDu
sumber
10

Mempertimbangkan Komponen Fungsi Bereaksi dan menggunakan Hook semakin populer akhir-akhir ini, saya akan memberikan contoh sederhana tentang cara Melewati data dari komponen anak ke orang tua

di Komponen Fungsi Induk kita akan memiliki:

import React, { useState, useEffect } from "react";

kemudian

const [childData, setChildData] = useState("");

dan meneruskan setChildData (yang melakukan pekerjaan yang mirip dengan this.setState di Komponen Kelas) ke Child

return( <ChildComponent passChildData={setChildData} /> )

di Komponen Anak pertama kita mendapatkan alat peraga penerima

function ChildComponent(props){ return (...) }

maka Anda dapat meneruskan data bagaimanapun juga seperti menggunakan fungsi handler

const functionHandler = (data) => {

props.passChildData(data);

}
Shayan Moghadam
sumber
3

Metode React.createClass telah usang dalam versi baru React, Anda dapat melakukannya dengan sangat sederhana dengan cara berikut membuat satu komponen fungsional dan komponen kelas lain untuk mempertahankan status:

Induk:

const ParentComp = () => {
  
  getLanguage = (language) => {
    console.log('Language in Parent Component: ', language);
  }
  
  <ChildComp onGetLanguage={getLanguage}
};

Anak:

class ChildComp extends React.Component {
    state = {
      selectedLanguage: ''
    }
    
    handleLangChange = e => {
        const language = e.target.value;
        thi.setState({
          selectedLanguage = language;
        });
        this.props.onGetLanguage({language}); 
    }

    render() {
        const json = require("json!../languages.json");
        const jsonArray = json.languages;
        const selectedLanguage = this.state;
        return (
            <div >
                <DropdownList ref='dropdown'
                    data={jsonArray} 
                    value={tselectedLanguage}
                    caseSensitive={false} 
                    minLength={3}
                    filter='contains'
                    onChange={this.handleLangChange} />
            </div>            
        );
    }
};

Sania Khushbakht Jamil
sumber
3
Hanya sebuah catatan ... Anda harus mereferensikan versi spesifik Bereaksi alih-alih "versi baru" untuk bukti di masa depan jawaban ini.
steve-o
3

dari komponen anak ke komponen induk seperti di bawah ini

komponen induk

class Parent extends React.Component {
   state = { message: "parent message" }
   callbackFunction = (childData) => {
       this.setState({message: childData})
   },
   render() {
        return (
            <div>
                 <Child parentCallback = {this.callbackFunction}/>
                 <p> {this.state.message} </p>
            </div>
        );
   }
}

komponen anak

class Child extends React.Component{
    sendBackData = () => {
         this.props.parentCallback("child message");
    },
    render() { 
       <button onClick={sendBackData}>click me to send back</button>
    }
};

Saya harap ini berhasil

Manoj Rana
sumber
2

dalam React v16.8+komponen fungsi, Anda dapat menggunakan useState()untuk membuat status fungsi yang memungkinkan Anda memperbarui status induk, lalu meneruskannya ke child sebagai atribut props, kemudian di dalam komponen child Anda dapat memicu fungsi status induk, berikut ini adalah cuplikan kerja :

const { useState , useEffect } = React;

function Timer({ setParentCounter }) {
  const [counter, setCounter] = React.useState(0);

  useEffect(() => {
    let countersystem;
    countersystem = setTimeout(() => setCounter(counter + 1), 1000);

    return () => {
      clearTimeout(countersystem);
    };
  }, [counter]);

  return (
    <div className="App">
      <button
        onClick={() => {
          setParentCounter(counter);
        }}
      >
        Set parent counter value
      </button>
      <hr />
      <div>Child Counter: {counter}</div>
    </div>
  );
}

function App() {
  const [parentCounter, setParentCounter] = useState(0);

  return (
    <div className="App">
      Parent Counter: {parentCounter}
      <hr />
      <Timer setParentCounter={setParentCounter} />
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById('react-root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react-root"></div>

AKAR
sumber
1

Anda bahkan dapat menghindari fungsi di induk memperbarui negara secara langsung

Dalam Komponen Induk:

render(){
 return(<Child sendData={ v => this.setState({item: v}) } />);
}

Dalam Komponen Anak:

demoMethod(){
   this.props.sendData(value);
}
Banzy
sumber
0

Idenya adalah mengirim panggilan balik ke anak yang akan dipanggil untuk memberikan data kembali

Contoh lengkap dan minimal menggunakan fungsi:

Aplikasi akan membuat Anak yang akan menghitung angka acak dan mengirimkannya kembali langsung ke induk, yang akan console.logmenghasilkan

const Child = ({ handleRandom }) => {
  handleRandom(Math.random())

  return <span>child</span>
}
const App = () => <Child handleRandom={(num) => console.log(num)}/>
Fabien Sa
sumber
0

Komponen Induk: -TimeModal

  handleTimeValue = (timeValue) => {
      this.setState({pouringDiff: timeValue});
  }

  <TimeSelection 
        prePourPreHours={prePourPreHours}
        setPourTime={this.setPourTime}
        isPrePour={isPrePour}
        isResident={isResident}
        isMilitaryFormatTime={isMilitaryFormatTime}
        communityDateTime={moment(communityDT).format("MM/DD/YYYY hh:mm A")}
        onSelectPouringTimeDiff={this.handleTimeValue}
     />

Catatan : - onSelectPouringTimeDiff = {this.handleTimeValue}

Dalam props panggilan Komponen Anak saat diperlukan

 componentDidMount():void{
      // Todo use this as per your scenrio
       this.props.onSelectPouringTimeDiff(pouringDiff);  
  }
Keshav Gera
sumber