311 votes

Comment passer des données d'un composant enfant à son parent dans ReactJS ?

J'essaie d'envoyer des données d'un composant enfant à son parent comme suit :

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

et voici le composant enfant :

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

Ce dont j'ai besoin, c'est de récupérer la valeur sélectionnée par l'utilisateur dans le composant parent. J'obtiens cette erreur :

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

Quelqu'un peut-il m'aider à trouver le problème ?

P.S. Le composant enfant crée une liste déroulante à partir d'un fichier json, et j'ai besoin que la liste déroulante affiche les deux éléments du tableau json l'un à côté de l'autre (comme : "aaa,english" comme premier choix !).

{  
   "languages":[  
      [  
         "aaa",
         "english"
      ],
      [  
         "aab",
         "swedish"
      ],
}

3 votes

<SelectLanguage onSelectLanguage={this.handleLanguage*Code*}/> une faute de frappe.

0 votes

@YuryTarabanko Merci, mais je reçois toujours la même erreur.

0 votes

@DavinTryon Comment dois-je l'ajouter ? J'ai essayé comme ça : handleLanguageCode: function(langValue) { this.setState({ language: langValue }).bind(this); }, Mais il renvoie une erreur : ncaught TypeError: Cannot read property 'bind' of undefined

358voto

Shubham Khatri Points 67350

Cela devrait fonctionner. Lorsque vous renvoyez l'accessoire, vous l'envoyez sous forme d'objet. Il vaut mieux l'envoyer sous forme de valeur ou l'utiliser comme objet dans le composant parent. Deuxièmement, vous devez formater votre objet json pour qu'il contienne des paires nom-valeur et utiliser la méthode suivante valueField et textField l'attribut de DropdownList

Réponse courte

Parent :

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

Enfant :

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

Détaillé :

EDIT :

Étant donné que React.createClass est déprécié à partir de la version 16.0, il est préférable d'aller de l'avant et de créer un composant React en prolongeant l'application React.Component . Le passage de données d'un composant enfant à un composant parent avec cette syntaxe se présente comme suit

Parent

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

Enfant

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

Utilisation de createClass syntaxe que le PO a utilisée dans sa réponse Parent

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

Enfant

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" 
    }, 
  ] 
}

0 votes

Merci Shubham, votre réponse a résolu le problème, mais elle n'affiche pas l'élément sélectionné dans la liste déroulante. Elle est vide après cela :/

1 votes

@Sarah Lors de la création de la liste déroulante, vous lui avez attribué la valeur this.state.selectedLanguage, qui n'est pas initialisée à une valeur quelconque. Cela peut être la cause du problème. Quel composant DropdownList utilisez-vous ? Si je le sais, je pourrai peut-être travailler sur ce composant pour résoudre le problème.

0 votes

Vous avez raison. Le site this.state.selectedLanguage semble toujours être nulle :/ J'utilise DropdownList à partir de react-widgets

135voto

Manisha Tan Points 621

Pour transmettre des données du composant enfant au composant parent

Dans la composante parentale :

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

Dans la composante enfant :

demoMethod(){
   this.props.sendData(value);
 }

24 votes

N'oubliez pas this.getData = this.getData.bind(this); dans le constructeur, comme vous pouvez obtenir this.setState n'est pas une fonction si vous voulez manipuler l'état dans getData.

57voto

Shayan Moghadam Points 632

Considérer React Composants fonctionnels et en utilisant Crochets sont de plus en plus populaires de nos jours, je vais vous donner un exemple simple de la manière de faire passer des données d'un composant enfant à un composant parent.

dans la composante de la fonction parentale, nous aurons :

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

puis

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

et en passant setChildData (qui fait un travail similaire à this.setState dans Class Components) à Child

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

dans Child Component, nous obtenons d'abord les props de réception

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

alors vous pouvez passer des données de n'importe quelle façon en utilisant une fonction de gestion.

const functionHandler = (data) => {

props.passChildData(data);

}

22voto

ROOT Points 10329

sur React v16.8+ vous pouvez utiliser la fonction useState() pour créer une fonction d'état qui vous permet de mettre à jour l'état du parent, puis de la transmettre à l'enfant en tant qu'attribut props. Dans le composant enfant, vous pouvez alors déclencher la fonction d'état du parent :

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>

15voto

MrDuDuDu Points 16

J'ai trouvé l'approche permettant de récupérer les données du composant enfant dans les parents lorsque j'en ai besoin.

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

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

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

  getMapPoint(){
    return this.Point;
  }
}

Cet exemple montre comment passer une fonction du composant enfant au parent et utiliser cette fonction pour obtenir des données du composant enfant.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X