web-dev-qa-db-fra.com

Comment obtenir les valeurs des composants enfants dans React

Je commence donc tout juste à utiliser React et je ne parviens pas à rassembler les valeurs d'entrée des entrées dans un composant enfant. Fondamentalement, je crée différents composants pour une forme volumineuse que je crée, puis dans le composant englobant, je souhaite collecter toutes les valeurs des entrées sur les enfants d'un objet que j'appelle des données, puis envoyer les entrées collectées dans un fichier POST AJAX demande (vous pouvez voir un exemple dans le dernier composant que j'ai créé). Je peux facilement extraire les valeurs lorsque je suis à l'intérieur des composants, mais je ne les ai pas extraites du composant parent.

Merci d'avance. Je ne fais que passer à travers les difficultés en ce moment avec React, de sorte que toute recommandation sur la manière de mieux structurer cela soit également, je suis tout ouïe!

Voici mes composants:

Premier composant

var StepOne = React.createClass({
  getInitialState: function() {
    return {title: '', address: '', location: ''};
  },
  titleChange: function(e) {
    this.setState({title: e.target.value});
  },
  addressChange: function(e) {
   this.setState({address: e.target.value});
  },
  locationChange: function(e) {
    this.setState({location: e.target.value});
  },
  render: function() {
    return (
      <div className="stepOne">
        <ul>
          <li>
            <label>Title</label>
            <input type="text" value={this.state.title} onChange={this.titleChange} />
          </li>
          <li>
            <label>Address</label>
            <input type="text" value={this.state.address} onChange={this.addressChange} />
          </li>
          <li>
            <label>Location</label>
            <input id="location" type="text" value={this.state.location} onChange={this.locationChange} />
          </li>
        </ul>
      </div>
    );
  }, // render
}); // end of component

Composante deux

var StepTwo = React.createClass({
  getInitialState: function() {
    return {name: '', quantity: '', price: ''}
  },
  nameChange: function(e) {
    this.setState({name: e.target.value});
  },
  quantityChange: function(e) {
    this.setState({quantity: e.target.value});
  },
  priceChange: function(e) {
    this.setState({price: e.target.value});
  },
  render: function() {
    return (
      <div>
      <div className="name-section">
        <div className="add">
          <ul>
            <li>
              <label>Ticket Name</label>
              <input id="name" type="text" value={this.state.ticket_name} onChange={this.nameChange} />
            </li>
            <li>
              <label>Quantity Available</label>
              <input id="quantity" type="number" value={this.state.quantity} onChange={this.quantityChange} />
            </li>
            <li>
              <label>Price</label>
              <input id="price" type="number" value={this.state.price} onChange={this.priceChange} />
            </li>
          </ul>
        </div>
      </div>
      </div>
    );
  }
});

Composant final pour collecter les données et soumettre une requête ajax

EventCreation = React.createClass({
 getInitialState: function(){
  return {}
},
submit: function (e){
  var self

  e.preventDefault()
  self = this

  var data = {
    // I want to be able to collect the values into this object then send it in the ajax request. I thought this sort of thing would work below:
    title: this.state.title,
  }

  // Submit form via jQuery/AJAX
  $.ajax({
    type: 'POST',
    url: '/some/url',
    data: data
  })
  .done(function(data) {
    self.clearForm()
  })
  .fail(function(jqXhr) {
    console.log('failed to register');
  });
},
render: function() {
    return(
      <form>
        <StepOne />
        <StepTwo />
        // submit button here
      </form>
    );
  }
});
7
luke

Définissez des méthodes dans les composants enfants qui renvoient les données souhaitées, puis dans le composant parent lors du rendu des enfants, définissez les références plus tard, lorsque vous souhaitez récupérer les données dont vous avez besoin, vous pouvez appeler ces méthodes sur les enfants.

StepOne = React.createClass({
    getData: function() {
        return this.state;
    }
});

StepTwo = React.createClass({
    getData: function() {
        return this.state;
    }
});

EventCreation = React.createClass({
    submit: function() {
        var data = Object.assign(
            {},
            this._stepOne.getData(),
            this._stepTwo.getData()
        );

        // ... do AJAX
    },

    render: function() {
        return (
            <StepOne ref={(ref) => this._stepOne = ref} />
            <StepTwo ref={(ref) => this._stepTwo = ref} />
        );
    }
});
7
Gaston Sanchez

De manière générale, vous souhaiterez transmettre une fonction du parent aux enfants en tant qu'accessoire. Lorsque les données des enfants changent, ils appellent cette fonction en tant que rappel. 

Cela présente le gros avantage de permettre à votre composant parent de garder la trace de tout l'état de votre application et de transmettre des tranches d'état en tant qu'accessoires à ses enfants, au lieu que chaque composant garde la trace de son propre état interne. ( C’est l’approche React du flux de données .)

Vos composants pourraient ressembler à ceci:

var StepOne = React.createClass({
  handleOnChange: function(e){
     this.props.handleChange(e.target.name, e.target.value);
  },      
  render: function() {
    return (
      <div className="stepOne">
        <ul>
          <li>
            <label>Title</label>
            <input type="text" name="title" value={this.props.title} onChange={this.handleChange} />
          </li>
          ...
        </ul>
      </div>
    );
  }, // render
}); // end of component

EventCreation = React.createClass({
 getInitialState: function(){
  return {}
},
handleChange: function(name, value){
    var tmp = {};
    tmp[name] = value;
    this.setState(tmp);
},
submit: function (e){
  var self

  e.preventDefault()
  self = this

  var data = {
    // I want to be able to collect the values into this object then send it in the ajax request. I thought this sort of thing would work below:
    title: this.state.title,
  }

  // Submit form via jQuery/AJAX
  $.ajax({
    type: 'POST',
    url: '/some/url',
    data: data
  })
  .done(function(data) {
    self.clearForm()
  })
  .fail(function(jqXhr) {
    console.log('failed to register');
  });
},
render: function() {
    return(
      <form>
        <StepOne handleChange={this.handleChange.bind(this)} title={this.state.title} .../>
        <StepTwo handleChange={this.handleChange.bind(this)} ... />
        // submit button here
      </form>
    );
  }
});
5
ajm

Tout d’abord, vous devez définir quelques références . Il vous permettra d’accéder facilement à certains éléments du DOM.

<input id="name" type="text" value={this.state.ticket_name} onChange={this.nameChange} ref="stepOneName"/>

Ensuite, dans votre méthode submit, vous pouvez le récupérer comme suit:

var data = {
name: this.refs.stepOneName.value
}

EDIT 1: Vous devez également ajouter une ref à vos composants:

render: function () { return ( // bouton de soumission ici ); } Un accès alors à votre élément:

var data = {
    name: this.refs.steOneRef.refs.stepOneName.value
    }

Je JSFiddled votre code ant il semble ok pour moi.

1
Zakaria

Voici une solution un peu plus faiblement couplée. Cela dépend de la définition de id pour chaque élément. En gros, vous appelez la fonction onChange des composants parents qui récupère et définit les données.

var StepOne = React.createClass({
  getInitialState: function() {
    return {title: '', address: '', location: ''};
  },
  _onChange(e) {
    // set your state if needed

    // call the parent function
    this.props.onChange(
        e.target.id,
        e.target.value
    )
  },
  render: function() {
    return (
      <div className="stepOne">
        <ul>
          <li>
            <label>Title</label>
            <input id="title" type="text" value={this.state.title} onChange={this._onChange.bind(this)} />
          </li>
          <li>
            <label>Address</label>
            <input id="address" type="text" value={this.state.address} onChange={this._onChange.bind(this)} />
          </li>
          <li>
            <label>Location</label>
            <input id="location" type="text" value={this.state.location} onChange={this._onChange.bind(this)} />
          </li>
        </ul>
      </div>
    );
  }, // render
}); // end of component

var StepTwo = React.createClass({
  getInitialState: function() {
    return {name: '', quantity: '', price: ''}
  },
  _onChange(e) {
    // set your state if needed

    // call the parent function
    this.props.onChange(
        e.target.id,
        e.target.value
    )
  },
  render: function() {
    return (
      <div>
      <div className="name-section">
        <div className="add">
          <ul>
            <li>
              <label>Ticket Name</label>
              <input id="name" type="text" value={this.state.ticket_name} onChange={this._onChange.bind(this)} />
            </li>
            <li>
              <label>Quantity Available</label>
              <input id="quantity" type="number" value={this.state.quantity} onChange={this._onChange.bind(this)} />
            </li>
            <li>
              <label>Price</label>
              <input id="price" type="number" value={this.state.price} onChange={this._onChange.bind(this)} />
            </li>
          </ul>
        </div>
      </div>
      </div>
    );
  }

  EventCreation = React.createClass({
    getInitialState: function(){
      return {}
    },
    _onChange(id, value) {
      this.formData[id] = value;
    },
    submit: function (e){
      var self

      e.preventDefault()
      self = this

      // Submit form via jQuery/AJAX
      $.ajax({
        type: 'POST',
        url: '/some/url',
        data: this.formData
      })
      .done(function(data) {
        self.clearForm()
      })
      .fail(function(jqXhr) {
        console.log('failed to register');
      });
  },
  render: function() {
      return(
        <form>
          <StepOne onChange={this.onChange.bind(this)}/>
          <StepTwo onChange={this.onChange.bind(this)}/>
          // submit button here
        </form>
      );
    }
});
0
Jack