2

I want to edit the guest data of my app. Why I click the edit button I take the ID, send it to GUEST class component and there I get the data from the state and then I send it to the input component (GuestForm). The problem is I am able to get the edit data in GuestForm component but I want to set the state somehow...so that I can see the data to be edited in the form pre-populated. Please help me I am new to React. I tried searching for different lifecycle methods but can't find any. After this I will use componentDidUpdate() to handle the update data. But please help me to populate the data from props to the form.

I am using Class Component. So please help me in this regard only.

Here is my Code index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Guest Register</title>
    <!--BOOTSTRAP, FONTAWESOME CDN-->
    <link
      rel="stylesheet"
      href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
      integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
      crossorigin="anonymous"
    />
    <link
      rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.css"
      integrity="sha256-46qynGAkLSFpVbEBog43gvNhfrOj+BmwXdxFgVK/Kvc="
      crossorigin="anonymous"
    />
    <!--END-->
  </head>
  <body class="bg-white">
    <!--ROOT ELEMENT-->
    <div id="root"></div>
    <!--END OF ROOT ELEMENT-->

    <!--REACT,REACT-DOM, BABEL CONFIG CDN-->
    <script
      crossorigin
      src="https://unpkg.com/react@16/umd/react.development.js"
    ></script>
    <script
      crossorigin
      src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"
    ></script>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
    <!--END OF CONFIG CDN-->

    <!--APPLICATION MAIN CODE-->
    <script src="App.js" type="text/babel"></script>
    <!--APPLICATION CODE END-->
  </body>
</html>

Here is my App.js

class GuestForm extends React.Component {
  state = {
    name: "",
    guestType: "",
    isEdit: false
  };

  changeName(name) {
    this.setState({
      name: name
    });
  }

  changeGuestType(type) {
    this.setState({
      guestType: type
    });
  }

  submitForm() {
    this.props.getGuestData(this.state);
    this.setState({
      name: "",
      guestType: ""
    });
  }

  componentDidUpdate = (prevProp, newProp) => {
    console.log("CDU: ", prevProp, newProp);
  };

  render() {
    return (
      <form>
        <div className="form-group">
          <input
            type="text"
            className="form-control"
            placeholder="Guest Name"
            value={
              this.props.dataToEdit.name
                ? this.props.dataToEdit.name
                : this.state.name
            } //value attribute doesn't works here
            onChange={event => this.changeName(event.target.value)}
            required
          />
        </div>
        <div className="form-group">
          <select
            className="form-control"
            value={
              this.props.dataToEdit.guestType
                ? this.props.dataToEdit.guestType
                : this.state.guestType
            }
            onChange={event => this.changeGuestType(event.target.value)}
            required
          >
            <option value="">Choose Type</option>
            <option value="VIP">VIP</option>
            <option value="NORMAL">Normal</option>
            <option value="CHIEF GUEST">Chief Guest</option>
          </select>
        </div>
        <button
          onClick={e => {
            e.preventDefault();
            this.submitForm();
          }}
          className="btn btn-primary"
        >
          {this.props.dataToEdit.isEdit ? "UPDATE" : "ADD"}
        </button>
      </form>
    );
  }
}

class GuestList extends React.Component {
  guestToDelete(id) {
    this.props.getTheIdToDelete(id);
  }
  guestToEdit(id) {
    this.props.getTheIdToEdit(id);
  }
  render() {
    return (
      <tr key={this.props.index}>
        <td scope="row">{this.props.name}</td>
        <td>{this.props.guestType}</td>
        <td>
          <a onClick={() => this.guestToEdit(this.props.index)}>
            <i className="far fa-edit text-info"></i>
          </a>
          &nbsp;&nbsp;
          <a onClick={() => this.guestToDelete(this.props.index)}>
            <i className="fa fa-trash-alt text-danger"></i>
          </a>
        </td>
      </tr>
    );
  }
}

class Guest extends React.Component {
  state = {
    guests: [],
    editGuestdata: []
  };

  getFormDataForGuests(data) {
    if (data.name && data.guestType) {
      this.setState(
        {
          guests: [...this.state.guests, data]
        },
        () => {
          console.log("GUEST:", this.state);
        }
      );
    }
  }

  guestToDelete(id) {
    let updatedGuest = [...this.state.guests];
    updatedGuest.splice(id, 1);
    this.setState({
      guests: updatedGuest
    });
  }

  guestToEdit(id) {
    let editData = {
      name: this.state.guests[id].name,
      guestType: this.state.guests[id].guestType,
      isEdit: true
    };
    this.setState({
      editGuestdata: editData
    });
  }

  render() {
    return (
      <div className="row text-center m-2">
        <div className="col-md-5 card mx-auto shadow m-1 p-3 col-xs-10">
          <h3>Guest Form</h3>
          <GuestForm
            dataToEdit={this.state.editGuestdata}
            getGuestData={data => this.getFormDataForGuests(data)}
          />
        </div>
        <div className="col-md-5 card mx-auto m-1 p-3 shadow col-xs-10">
          <table className="table table-striped">
            <thead>
              <tr>
                <th>Name</th>
                <th>Guest Type</th>
                <th>Edit/Delete</th>
              </tr>
            </thead>
            <tbody>
              {this.state.guests.map((data, index) => {
                return (
                  <GuestList
                    getTheIdToDelete={id => this.guestToDelete(id)}
                    getTheIdToEdit={id => this.guestToEdit(id)}
                    index={index}
                    name={data.name}
                    guestType={data.guestType}
                  />
                );
              })}
            </tbody>
          </table>
        </div>
      </div>
    );
  }
}

ReactDOM.render(<Guest />, document.getElementById("root"));

HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133

2 Answers2

0

Try accessing the values from 'dataToEdit' in the form component.

<input
   type="text"
   className="form-control"
   placeholder="Guest Name"
   value={this.props.dataToEdit.name} //this will pull in as props not state
   onChange={event => this.changeName(event.target.value)}
   required
/>

If it is still not working then the dataToEdit is not being set properly.

Lucas Claude
  • 331
  • 1
  • 7
  • This works for me to show the value in input field. But I want to get the value in form from the state. Is there any way or any lifecycle method which can access the props value and through that I can set the state. And then the input can be populated with the edit data value. Please can u try to edit the code...these are the only 2 files for this app. Waiting for your response. – Mayank Kumar Feb 01 '20 at 08:31
  • Actually your code helped me....but it should be like having a condition in value like this ** this.changeName(event.target.value)} required />** This is what I wanted thanks for the efforts. :) – Mayank Kumar Feb 01 '20 at 12:38
  • It solved my problem of showing value in the form. But Now I am not able to edit the value. Please see the code I updated it. But Now I am not able to edit the input field. – Mayank Kumar Feb 01 '20 at 13:02
0

Change your state object like below in GuestForm

It will initialize your app initial state from the props.

 state = {
    name: this.props.name,
    guestType: this.props.guestType,
    isEdit: false
  };

You can use the constructor as well to initialize this.

constructor (props){
super(props)
this.state = {
        name: props.name,
        guestType: props.guestType,
        isEdit: false
      };
}

You can try the gerDerivedStateFromProps lifecycle method to initialize the state with props from parent.

 state = {
           name: '',
           guestType: '',
           isEdit: false
       };

static getDerivedStateFromProps(nextProps, prevState) {

  return {
    name: nextProps.name,
    guestType: nextProps.guestType,
    isEdit: false
  };
}

After this you can update the state with your regular method like as setState() and update the values.

Bhagwat K
  • 2,982
  • 2
  • 23
  • 33
  • Not working. I am getting the props data in the render() function. But I guess we cannot directly change the state like you suggested. It does nothing....can you please copy the two code try it...in your system. And tell me in which react lifecycle method I can get the props value and set the state. so as to view the edit data pre-populated in the form. – Mayank Kumar Feb 01 '20 at 08:06
  • 1. Constructor is called only once. So this will not work and even I am not getting the data in it. 2. getDerivedStateFromProps is a static method I am getting the edit data inside it ...but we cannot use the **setState()** inside it as it is a static function. So it will also not work. Actually I tried all this yesterday as well before posting this question here. 3. you cannot directly set the values inside the state variable as you done in step one... – Mayank Kumar Feb 01 '20 at 09:41
  • None of your solutions worked. I will suggest you to try it on your system. once you click the edit symbol for any item on the right. Just populate its value in the form. I want to access values in form only through **this.state**. So please try to take care of that. Just do this much. I am facing issue to do this only. After that I will take care of the updation part. Thanks for your efforts :) – Mayank Kumar Feb 01 '20 at 09:48
  • ** this.changeName(event.target.value)} required />** this helped me solve my issue. Thanks for your efforts. – Mayank Kumar Feb 01 '20 at 12:34
  • I solved my problem of showing value in the form for update. But Now I am not able to edit the value. Please see the code I updated it. But Now I am not able to edit the input field. – Mayank Kumar Feb 01 '20 at 13:02