How to get values from child components in React

Viewed 51166

So I am just starting to use React and am having trouble gathering the input values of inputs within a child component. Basically, I am creating different components for a large form I am making, then in the encompassing component, I want to collect all the values of inputs on the children in an object I am calling data, and then send that collected input into a POST AJAX request (you can see an example in the last component I made). I can pull the values easily enough when I am inside of the components, but pulling them from the parent component I haven't figured out.

Thanks in advance. Just going through the pains right now with React so any recommendations on how to structure this better as well, I am all ears!

Here are my components:

Component one

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

Component two

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

Final component to collect data and submit ajax request

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

I use this approach to gathering values of form fields from the child component :

Parent Component:

import { useEffect, useState } from "react";
import DetailFields from "./DetailFields";

export default function ParentComponent(props) {
  //Set initial Values
  const [model, setModel] = useState(props.initModel);

  useEffect(() => {
    setModel(props.initModel);
  }, [props.initModel]);

  //  call API
  const handleSubmit = (event) => {
    //...Here you have model values and you can send it to api
    callApi(model);
  };

  // Set Values from the input to the model when the values changed
  const handleChange = (event) => {
    // get the value of the field
    const value = event?.target?.value;
    //set it in the model
    setModel({
      ...model,
      [event.target.name]: value,
    });
  };

  return (
    <form>
      <div>
        <DetailFields
          model={model}
          // pass the function to child component
          handleChange={handleChange}
        />

        <input type="submit" value="Submit" onClick={handleSubmit} />
      </div>
    </form>
  );
}

Child Component:

import React from "react";

export default function DetailFields(props){
  return (

     <div className="stepOne">
          <ul>
               <li>
                    <label>First Field</label>
                    <input id="FirstField" type="text" value={props.model.FirstField || ""} onChange={props.handleChange} />
               </li>
               <li>
                    <label>Second Field</label>
                    <input id="SecondField" type="text" value={props.model.SecondField || ""} onChange={props.handleChange} />
               </li>
          </ul>
     </div>

  );
};
Related