0

I am a ReactJs newbie and I am here with attaching the code for the same . I have 3 components Forms with Addresses , Phones and Emails . Forms with Addresses is the Parent Component .Phones and Emails are the child components of Forms, I am unable to access the state objects of phones and Emails from Parent component , I am aware of how to send the parent state object to the child components , But the other way around I am not aware of it , I tried callback and so forth but that didn't help . Please provide your inputs.

import React, { Component } from 'react';
    import PropTypes from 'prop-types';
    import {
      Panel,
      Button,
      Col,
      PageHeader,
      ControlLabel,
      FormControl,
      HelpBlock,
      FormGroup,
      Checkbox,
      Form,
      Radio,
      InputGroup,
      Glyphicon } from 'react-bootstrap';

    import FormControlFeedback from 'react-bootstrap/lib/FormControlFeedback';
    import FormControlStatic from 'react-bootstrap/lib/FormControlStatic';
    import InputGroupAddon from 'react-bootstrap/lib/InputGroupAddon';
    import Email from './Email';
    import Phone from './Phone';

    const spacing = {
      marginRight: "20px",
      marginbottom: "20px"
    }
    const buttonalignment = {
      marginLeft: "81px",
      marginbottom: "20px"
    }




    class displayForms extends React.Component {

      constructor(props) {
        super(props);

        //  this.state.products = [];
        this.state = {};
        this.state.filterText = "";
        this.state.products = [
          {
            id: 1,
          Field1: "",
           Field2: '',
           Field3: '',
           Field4: '',
           Field5:'',
           Field6: '',
           Field7: ''
          }
        ];

      }
      handleUserInput(filterText) {
        this.setState({filterText: filterText});
      };
      handleRowDel(product) {
        var index = this.state.products.indexOf(product);
        this.state.products.splice(index, 1);
        this.setState(this.state.products);
      };

      handleAddEvent(evt) {
        var id = (+ new Date() + Math.floor(Math.random() * 999999)).toString(36);
        var product = {
          id: id,
          Field1: "",
           Field2: '',
           Field13: '',
           Field14: '',
           Field5:'',
           Field6: '',
           Field7: ''

        }
        this.state.products.push(product);
        this.setState(this.state.products);

      }

      handleProductTable(evt) {
        var item = {
          id: evt.target.id,
          name: evt.target.name,
          value: evt.target.value
        };
        console.log('item.value[0] in address',item.value);
        console.log('item.value[1] in address',item.value);
        console.log('item.value[2] in address',item.value);
    var products = this.state.products.slice();
      var newProducts = products.map(function(product) {

        for (var key in product) {
          if (key == item.name && product.id == item.id) {
            product[key] = item.value;

          }
        }
        return product;
      });
        this.setState({products:newProducts});
      //  console.log(this.state.products);
      };
      render() {

        return (
          <div>

            <ProductTable onProductTableUpdate={this.handleProductTable.bind(this)} onRowAdd={this.handleAddEvent.bind(this)} onRowDel={this.handleRowDel.bind(this)} products={this.state.products} filterText={this.state.filterText}/>
            <Email />
            <Phone />
          </div>
        );

      }

    }


    class ProductTable extends React.Component {

    handleSubmit(event) {
    event.preventDefault();
    //myFunction();
    console.log('In Handle submit function');
    console.log('Addresses[0]:after get', this.props.products[0].Field1);
    console.log('Addresses[0]:after get', this.props.products[0].Field2);
    console.log('Addresses[0]:after get', this.props.products[0].Field3);
    console.log('Addresses[0]:after get', this.props.products[0].Field4);
    const form = event.target;
    const data = new FormData(form);
    const arrayValue = [];
    var i = 0;
    console.log('Data from Form:', data);
    for (let name of data.keys()) {
      const input = form.elements[name];
      const parsedValue = data.get(name);
      console.log('name', name);
      console.log('parsedValue', parsedValue);
      if (typeof (parsedValue) == 'undefined' || parsedValue == null) {
        console.log('Not Defined or Not Null')
        arrayValue[i] = "";
        data.set(name, "");
      }
      else {
        data.set(name, parsedValue);
        arrayValue[i] = parsedValue;
      }
      i = i + 1;
    }

    console.log('arrayValue[4]:after get', arrayValue[4]);
    console.log('arrayValue[1]:after get', arrayValue[1]);
    console.log('arrayValue[3]:after get', arrayValue[3]);
    //console.log('Addresses[0]:after get', this.props.products[0]);

  }

      render() {
        var onProductTableUpdate = this.props.onProductTableUpdate;
        var rowDel = this.props.onRowDel;
        var filterText = this.props.filterText;
        var product = this.props.products.map(function(product) {
          if (product.Address_Line.indexOf(filterText) === -1) {
            return;
          }
          return (<ProductRow onProductTableUpdate={onProductTableUpdate} product={product} onDelEvent={rowDel.bind(this)} key={product.id}/>)
        });
        return (

          <div id="test">
                <div className="row">
                  <div className="col-lg-12">
                    <PageHeader>Test App</PageHeader>
                  </div>
                </div>
                <form onSubmit={this.handleSubmit}>
                  <table>
                    <tr>
                    <td>
                        <FormGroup style={spacing}>
                          <ControlLabel>ID</ControlLabel>
                          <FormControl
                            id="field1" name="field1"
                            type="text"
                            placeholder="Enter Text"
                          />
                        </FormGroup>
                      </td>
                      </tr>
                      <tr>
                      <td>
                      <FormGroup style={spacing}>
                          <ControlLabel> Month</ControlLabel>
                          <FormControl componentClass="select" id="MM" name="MM" placeholder="select">
                            <option value="01">01</option>
                            <option value="02">02</option>
                            <option value="03">03</option>
                            <option value="04">04</option>
                            <option value="05">05</option>
                            <option value="06">06</option>
                            <option value="07">07</option>
                            <option value="08">08</option>
                            <option value="09">09</option>
                            <option value="10">10</option>
                            <option value="11">11</option>
                            <option value="12">12</option>
                          </FormControl>
                        </FormGroup>
                      </td>
                      <td>
                      <FormGroup style={spacing}>
                          <ControlLabel> Day</ControlLabel>
                          <FormControl componentClass="select" id="DD" name="DD" placeholder="select">
                            <option value="01">01</option>
                            <option value="02">02</option>
                            <option value="03">03</option>
                            <option value="04">04</option>
                            <option value="05">05</option>
                            <option value="06">06</option>
                            <option value="07">07</option>
                            <option value="08">08</option>
                            <option value="09">09</option>
                            <option value="10">10</option>
                            <option value="11">11</option>
                            <option value="12">12</option>
                            <option value="13">13</option>
                            <option value="14">14</option>
                            <option value="15">15</option>
                            <option value="16">16</option>
                            <option value="17">17</option>
                            <option value="18">18</option>
                            <option value="19">19</option>
                            <option value="20">20</option>
                            <option value="21">21</option>
                            <option value="22">22</option>
                            <option value="23">23</option>
                            <option value="24">24</option>
                            <option value="25">25</option>
                            <option value="26">26</option>
                            <option value="27">27</option>
                            <option value="28">28</option>
                            <option value="29">29</option>
                            <option value="30">30</option>
                            <option value="31">31</option>
                          </FormControl>
                        </FormGroup>
                      </td>
                  </table>
                  </form>
          <div className="col-lg-15">
          <th>Address</th>
          <button type="button" onClick={this.props.onRowAdd} className="btn btn-success pull-right">+</button>
            <table className="table table-bordered">
              <thead>
                <tr>
                  <th>Field1</th>
                  <th>Field2</th>
                  <th>Field3</th>
                  <th>field4</th>
                  <th>field5</th>
                  <th>field6</th>
                  <th>field7</th>
                </tr>
              </thead>

              <tbody>
                {product}

              </tbody>

            </table>
          </div>
          </div>
        );

      }

    }

    class ProductRow extends React.Component {
      onDelEvent() {
        this.props.onDelEvent(this.props.product);

      }
      render() {

        return (
          <tr className="eachRow">
            <EditableCell onProductTableUpdate={this.props.onProductTableUpdate} cellData={{
              "type": "Field1",
              value: this.props.product.Field1,
              id: this.props.product.id
            }}/>
            <EditableCell onProductTableUpdate={this.props.onProductTableUpdate} cellData={{
              type: "Field2",
              value: this.props.product.Field2,
              id: this.props.product.id
            }}/>
            <EditableCell onProductTableUpdate={this.props.onProductTableUpdate} cellData={{
              type: "Field3",
              value: this.props.product.Field3,
              id: this.props.product.id
            }}/>
            <EditableCell onProductTableUpdate={this.props.onProductTableUpdate} cellData={{
              type: "Field4",
              value: this.props.product.Field4,
              id: this.props.product.id
            }}/>
             <EditableCell onProductTableUpdate={this.props.onProductTableUpdate} cellData={{
              type: "Field5",
              value: this.props.product.Field5,
              id: this.props.product.id
            }}/>
            <EditableCell onProductTableUpdate={this.props.onProductTableUpdate} cellData={{
              type: "Field6",
              value: this.props.product.Field6,
              id: this.props.product.id
            }}/>
            <EditableCell onProductTableUpdate={this.props.onProductTableUpdate} cellData={{
              type: "Field7",
              value: this.props.product.Field7,
              id: this.props.product.id
            }}/>
            <td className="del-cell">
              <input type="button" onClick={this.onDelEvent.bind(this)} value="REMOVE" className="del-btn"/>
            </td>
          </tr>
        );

      }

    }
    class EditableCell extends React.Component {

      render() {
        return (
          <td>
            <input type='text' name={this.props.cellData.type} id={this.props.cellData.id} value={this.props.cellData.value} onChange={this.props.onProductTableUpdate}/>
          </td>
        );

      }

    }


    displayForms.contextTypes = { setTitle: PropTypes.func.isRequired };

    export default displayForms;

//import React, { PropTypes , Component } from 'react';
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import {
  Panel,
  Button,
  Col,
  PageHeader,
  ControlLabel,
  FormControl,
  HelpBlock,
  FormGroup,
  Checkbox,
  Form,
  Radio,
  InputGroup,
  Glyphicon } from 'react-bootstrap';

import FormControlFeedback from 'react-bootstrap/lib/FormControlFeedback';
import FormControlStatic from 'react-bootstrap/lib/FormControlStatic';
import InputGroupAddon from 'react-bootstrap/lib/InputGroupAddon';





class Phone extends React.Component {

  constructor(props) {
    super(props);

    //  this.state.phones = [];
    this.state = {};
    this.state.filterText = "";
    this.state.phones = [
      {
        id: 1,
       Field1: '',
       Field2: '',
       Field3: '',
       Field4: '',
       Field5: ''
      }
    ];

  }
  handleUserInput(filterText) {
    this.setState({filterText: filterText});
  };
  handleRowDel(phone) {
    var index = this.state.phones.indexOf(phone);
    this.state.phones.splice(index, 1);
    this.setState(this.state.phones);
  };

  handleAddEvent(evt) {
    var id = (+ new Date() + Math.floor(Math.random() * 999999)).toString(36);
    var phone = {
      id: id,
      Phone_Number: '',
       Type: '',
       Receive_Calls: '',
       Receive_Texts: '',
       Preferred_Phone_Number: ''

    }
    this.state.phones.push(phone);
    this.setState(this.state.phones);

  }

  handlephoneTable(evt) {
    var item = {
      id: evt.target.id,
      name: evt.target.name,
      value: evt.target.value
    };
    console.log('item.value in phone',item.value);
var phones = this.state.phones.slice();
  var newphones = phones.map(function(phone) {

    for (var key in phone) {
      if (key == item.name && phone.id == item.id) {
        phone[key] = item.value;

      }
    }
    return phone;
  });
    this.setState({phones:newphones});
  //  console.log(this.state.phones);
  };
  render() {

    return (
      <div>

        <PhoneTable onphoneTableUpdate={this.handlephoneTable.bind(this)} onRowAdd={this.handleAddEvent.bind(this)} onRowDel={this.handleRowDel.bind(this)} phones={this.state.phones} filterText={this.state.filterText}/>
      </div>
    );

  }

}


class PhoneTable extends React.Component {

  render() {
    var onphoneTableUpdate = this.props.onphoneTableUpdate;
    var rowDel = this.props.onRowDel;
    var filterText = this.props.filterText;
    var phone = this.props.phones.map(function(phone) {
      if (phone.Type.indexOf(filterText) === -1) {
        return;
      }
      return (<PhoneRow onphoneTableUpdate={onphoneTableUpdate} phone={phone} onDelEvent={rowDel.bind(this)} key={phone.id}/>)
    });
    return (
      <div>

    <th>Phone</th>
      <button type="button" onClick={this.props.onRowAdd} className="btn btn-success pull-right">Add</button>
        <table className="table table-bordered">
          <thead>
            <tr>
              <th>Phone_Number</th>
              <th>Type</th>
              <th>Receive_Calls</th>
              <th>Receive_Texts</th>
              <th>Preferred_Phone_Number</th>
            </tr>
          </thead>

          <tbody>
            {phone}

          </tbody>

        </table>
      </div>
    );

  }

}

class PhoneRow extends React.Component {
  onDelEvent() {
    this.props.onDelEvent(this.props.phone);

  }
  render() {

    return (
      <tr className="eachRow">
        <EditableCell onphoneTableUpdate={this.props.onphoneTableUpdate} cellData={{
          "type": "Field1",
          value: this.props.phone.Field1,
          id: this.props.phone.id
        }}/>
        <EditableCell onphoneTableUpdate={this.props.onphoneTableUpdate} cellData={{
          type: "Field2",
          value: this.props.phone.Field2,
          id: this.props.phone.id
        }}/>
        <EditableCell onphoneTableUpdate={this.props.onphoneTableUpdate} cellData={{
          type: "Field3",
          value: this.props.phone.Field3,
          id: this.props.phone.id
        }}/>
        <EditableCell onphoneTableUpdate={this.props.onphoneTableUpdate} cellData={{
          type: "Field4",
          value: this.props.phone.Field4,
          id: this.props.phone.id
        }}/>
        <EditableCell onphoneTableUpdate={this.props.onphoneTableUpdate} cellData={{
          type: "Field5",
          value: this.props.phone.Field5,
          id: this.props.phone.id
        }}/>
        <td className="del-cell">
          <input type="button" onClick={this.onDelEvent.bind(this)} value="REMOVE" className="del-btn"/>
        </td>
      </tr>
    );

  }

}
class EditableCell extends React.Component {

  render() {
    return (
      <td>
        <input type='text' name={this.props.cellData.type} id={this.props.cellData.id} value={this.props.cellData.value} onChange={this.props.onphoneTableUpdate}/>
      </td>
    );

  }

}


export default Phone;

1 Answer 1

1

You can pass a callback from the parent component to child component so the child can update the state in the parent. Here's a sample code demonstrating this:

class Parent extends React.Component {
  constructor(props) {
    super(props);
      this.state = {
        phone: ''
      }
    this.phoneChange = this.phoneChange.bind(this);
  }
  
  componentDidUpdate() {
    console.log('Parent state:', this.state.phone);
  }

  phoneChange(phone) {
    console.log('child value', phone)
    this.setState({phone});
  }

  render() {
    return (
    <div>
      Phone:
      <Child
      phoneChange = {
        this.phoneChange
      }
      />
    </div>)
  }
}

class Child extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        phone: ''
      }
      this.handleChange = this.handleChange.bind(this);
    }

    handleChange(e) {
      const phone = e.target.value;
      this.setState({
        phone
      })
      this.props.phoneChange(phone);
    }

    render() {
      return ( < input value = {
          this.state.phone
        }
        onChange = {
          this.handleChange
        }
      />);
   }
}

ReactDOM.render( < Parent / > ,
  document.getElementById('root')
);
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>

<div id="root" />

Sign up to request clarification or add additional context in comments.

8 Comments

Thanks a lot , But how do I do it in my case , you are passing the state object from parent to child , My case is different , My child component phone has phones as state object and that needs to be accessed in parent Forms component , How do I do that ? I tried callback , It didn't seem to work , Thanks again, React Newbie here
@Ice_Queen I updated the code. The child component now has its own state but passing its value to the parent using the callback.
@Ice_Queen I am passing only phone inside this.props.phoneChange(phone). The idea is the same and you can pass your whole state instead of phone. That makes it accessible in the parent. As a side note, instead of passing states back and forth between components, you can have a central store using Redux. That makes life much more easier.
Thanks lot for the example , I am reading up on redux too , I am able to console.log the child component's state object but in order to use it other functions in the parent component how do I assign it to a parent component's stae object , Suppose I have phones as the state object in the parent component and I did this in phoneChange function this.setState({phones:phone}) itis not get assigned to phones which is the state of parent object , Thanks again and please suggest
Any suggestions please ? Your help is much appreciated
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.