Wie übergebe ich Daten von der untergeordneten Komponente in ReactJS an die übergeordnete Komponente?

210

Ich versuche, Daten von einer untergeordneten Komponente wie folgt an die übergeordnete Komponente zu senden:

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>
        );
});

und hier ist die untergeordnete Komponente:

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>            
        );
    }
});

Ich muss den ausgewählten Wert vom Benutzer in der übergeordneten Komponente abrufen. Ich erhalte diesen Fehler:

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

Kann mir jemand helfen, das Problem zu finden?

PS Die untergeordnete Komponente erstellt ein Dropdown-Menü aus einer JSON-Datei, und ich benötige die Dropdown-Liste, um beide Elemente des JSON-Arrays nebeneinander anzuzeigen (z. B. "aaa, englisch" als erste Wahl!).

{  
   "languages":[  
      [  
         "aaa",
         "english"
      ],
      [  
         "aab",
         "swedish"
      ],
}
Birish
quelle
3
<SelectLanguage onSelectLanguage={this.handleLanguage*Code*}/> ein Tippfehler.
Yury Tarabanko
@ YuryTarabanko Danke, aber immer noch den gleichen Fehler
Birish
@DavinTryon Wie soll ich es hinzufügen? Ich habe es so versucht: handleLanguageCode: function(langValue) { this.setState({ language: langValue }).bind(this); },Aber es gibt einen Fehler zurück:ncaught TypeError: Cannot read property 'bind' of undefined
Birish
2
@DavinTryon createClassbindet nicht reagierende Methoden automatisch.
Yury Tarabanko
@OP könnten Sie eine Geige erstellen, die das Problem demonstriert?
Yury Tarabanko

Antworten:

258

Das sollte funktionieren. Während Sie die Requisite zurücksenden, senden Sie sie als Objekt, anstatt sie als Wert zu senden, oder verwenden sie alternativ als Objekt in der übergeordneten Komponente. Zweitens müssen Sie Ihr json-Objekt so formatieren, dass es Name-Wert-Paare sowie Verwendung valueFieldund textFieldAttribut von enthältDropdownList

Kurze Antwort

Elternteil:

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

Kind:

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

Detailliert:

BEARBEITEN:

Da React.createClass ab Version 16.0 veraltet ist, ist es besser, eine React-Komponente durch Erweitern zu erstellen React.Component. Das Übergeben von Daten von der untergeordneten Komponente an die übergeordnete Komponente mit dieser Syntax sieht folgendermaßen aus

Elternteil

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>
        )
     }
}

Kind

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>            
        );
    }
}

Verwendung der createClassSyntax, die das OP in seiner Antwort Parent verwendet hat

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>
        );
});

Kind

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
quelle
Dank Shubham hat Ihre Antwort das Problem behoben, aber das ausgewählte Element wird nicht in der Dropdown-Liste angezeigt.
Danach
@Sarah Beim Erstellen der dropDownList haben Sie den Wert this.state.selectedLanguage zugewiesen und dieser Wert wird nicht mit einem Wert initialisiert. Das könnte das Problem sein. Welche DropdownList-Komponente verwenden Sie? Wenn ich weiß, kann ich vielleicht daran arbeiten, um das Problem zu beheben.
Shubham Khatri
Du hast recht. Das this.state.selectedLanguagescheint immer null zu sein: / Ich benutze DropdownList vonreact-widgets
Birish
@Sarah Ich habe eine kleine Änderung am Code vorgenommen, einschließlich der Bindung des Werts an die Funktion onChange und der Festlegung eines Anfangszustandswerts. Versuchen Sie dies und sagen Sie mir, ob es für Sie funktioniert
Shubham Khatri
Gibt einen Fehler zurück : Uncaught ReferenceError: value is not defined. Ich habe diese Änderung vorgenommen: onChange={this.handleLangChange.bind(this, this.value)}und es wird kein Fehler zurückgegeben, aber der ausgewählte Wert wird immer noch nicht
angezeigt
108

Übergeben von Daten von der untergeordneten Komponente an die übergeordnete Komponente

In der übergeordneten Komponente:

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

In der untergeordneten Komponente:

demoMethod(){
   this.props.sendData(value);
 }
Manisha Tan
quelle
15
Vergessen Sie nicht this.getData = this.getData.bind(this);im Konstruktor, da dies möglicherweise angezeigt wird. SetState ist keine Funktion, wenn Sie den Status in getData bearbeiten möchten.
Miro J.
12

Ich habe den Ansatz gefunden, wie man Daten von untergeordneten Komponenten in Eltern erhält, wenn ich sie brauche.

Elternteil:

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>
    )
  }
}

Kind:

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

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

  getMapPoint(){
    return this.Point;
  }
}

Dieses Beispiel zeigt, wie die Funktion von der untergeordneten Komponente an die übergeordnete Komponente übergeben und mit dieser Funktion Daten vom untergeordneten Element abgerufen werden.

MrDuDuDu
quelle
10

Angesichts der Tatsache, dass Komponenten von Reaktionsfunktionen und die Verwendung von Hooks heutzutage immer beliebter werden, werde ich ein einfaches Beispiel für die Übergabe von Daten von einer untergeordneten an eine übergeordnete Komponente geben

In der übergeordneten Funktionskomponente haben wir:

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

dann

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

und Übergeben von setChildData (die einen ähnlichen Job wie this.setState in Klassenkomponenten ausführen) an Child

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

In Child Component erhalten wir zuerst die empfangenden Requisiten

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

dann können Sie Daten trotzdem wie mit einer Handlerfunktion übergeben

const functionHandler = (data) => {

props.passChildData(data);

}
Shayan Moghadam
quelle
3

Die React.createClass-Methode ist in der neuen Version von React veraltet. Sie können dies ganz einfach auf folgende Weise tun: Erstellen Sie eine Funktionskomponente und eine andere Klassenkomponente, um den Status beizubehalten:

Elternteil:

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

Kind:

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
quelle
3
Nur eine Anmerkung ... Sie sollten die spezifische Version von React anstelle von "der neuen Version" referenzieren, um diese Antwort zukunftssicher zu machen.
Steve-o
3

von der untergeordneten Komponente zur übergeordneten Komponente wie unten

übergeordnete Komponente

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>
        );
   }
}

untergeordnete Komponente

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

Ich hoffe diese Arbeit

Manoj Rana
quelle
1

Sie können sogar vermeiden, dass die übergeordnete Funktion den Status direkt aktualisiert

In der übergeordneten Komponente:

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

In der untergeordneten Komponente:

demoMethod(){
   this.props.sendData(value);
}
Banzy
quelle
1

In der React v16.8+Funktionskomponente können Sie useState()einen Funktionsstatus erstellen, mit dem Sie den übergeordneten Status aktualisieren und dann als Requisitenattribut an das untergeordnete Element weitergeben können. In der untergeordneten Komponente können Sie die übergeordnete Statusfunktion auslösen. Das Folgende ist ein funktionierendes Snippet ::

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>

WURZEL
quelle
0

Die Idee ist, einen Rückruf an das Kind zu senden, der aufgerufen wird, um die Daten zurückzugeben

Ein vollständiges und minimales Beispiel mit Funktionen:

Die App erstellt ein untergeordnetes Element, das eine Zufallszahl berechnet und diese direkt an das übergeordnete Element zurücksendet. console.logDies führt zum Ergebnis

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

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

Übergeordnete Komponente: -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}
     />

Hinweis : - onSelectPouringTimeDiff = {this.handleTimeValue}

Rufen Sie in der untergeordneten Komponente bei Bedarf Requisiten auf

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