1

I'm new to React and have created a dynamic tablefrom a JSON received from the back-end server that I have. For each table row I have a button that opens to a dropdown which has two options - to edit the information in the row and to delete the row. I've made a separate component for the dropdown button and presently am passing the ID of the row to it. With the present code, I'm able to delete the row but can only see the change on refreshing the page. I've looked at other answers to problems like mine with people saying the state needs to be updated but I'm confused about how to go about it in this case.

EDIT: I'm not use anything for managing state. Just plain simple React

This is the code for the table that gets rendered :-

<table className="table">
          <thead>
            <tr>
              <th>S. NO.</th>
              <th>NAME</th>
              <th>AGE</th>
              <th>ADDRESS</th>
              <th></th>
            </tr>
          </thead>
          <tbody>
            {this.state.personData.map((Row, idx) => (
              <tr key={Row.id}>
                <td>{idx + 1}</td>
                <td>{Row.name}</td>
                <td>{Row.age}</td>
                <td>{Row.addr}</td>
                <td>
                  {" "}
                  <DropDownButton id={Row.id} />{" "}
                </td>
              </tr>
            ))}
          </tbody>
        </table>

This is the code in the DropDownButton component :-

handleDelete() {
    console.log("ID " + this.props.id);

    fetch("http://localhost/person/" + this.props.id, {
      method: "DELETE",
      headers: {
        "Access-Control-Allow-Origin": "*",
        "Access-Control-Allow-Headers": "Content-Type"
      }
    })
      .catch(error => console.log("Error:", error))
      .then(response => console.log("Success:", response));
  }
  render() {
    return (
      <React.Fragment>
        <div className="dropdown">
          <button
            type="button"
            className="btn dropdown-toggle dropdownButton"
            data-toggle="dropdown"
          >
            OPTIONS
          </button>
          <div className="dropdown-menu">
            <p className="dropdown-item" onClick={this.handleEdit}>
              EDIT
            </p>
            <p className="dropdown-item" onClick={this.handleDelete}>
              DELETE
            </p>
          </div>
        </div>
      </React.Fragment>
    );
  }
}
sindhugauri
  • 189
  • 2
  • 14
  • Inside ```handleDelete()``` function inside ```.then(response)``` block, try like ```.then(response => { this.setState({personData : response}) }``` If the response is your new array data then it will work.. – Maniraj Murugan Mar 06 '20 at 05:07
  • @ManirajMurugan actually the problem is that the original data array personData is in the parent component that passes the ID of each row to the DropDownButton component. How do I pass this data variable to the DropDownButton component? – sindhugauri Mar 06 '20 at 05:11
  • You can pass the data like `````` in table component and in your dropdown button component you can get it like, ```this.props.persons```.. – Maniraj Murugan Mar 06 '20 at 05:17
  • @ManirajMurugan with this approach I get a 'TypeError:Cannot assign to read only property' – sindhugauri Mar 06 '20 at 07:38
  • Where exactly you are getting this error?? In which file and variable?? – Maniraj Murugan Mar 06 '20 at 07:42
  • @ManirajMurugan what I was trying to do was to send a get request after the delete request and update the 'persons' state accordingly. So when I did this.props.persons = response, I got the mentioned error – sindhugauri Mar 06 '20 at 07:58
  • I have never said you to assign the value to props and if you assign any vaues to props then it will throw only above mentioned error because it is read only.. Anyhow you got the solution of what you want it seems.. – Maniraj Murugan Mar 06 '20 at 08:03

2 Answers2

1

In your parent component you need to make a callback method that will remove the data from this.state.personData like the method I wrote below


onDelete = (id) => {
  this.setState({
    ...this.state,
    personData: this.state.personData.filter((row) => row.id !== id)
  });
}

render = () => {
  return (
    <table className="table">
      <thead>
        <tr>
          <th>S. NO.</th>
          <th>NAME</th>
          <th>AGE</th>
          <th>ADDRESS</th>
          <th></th>
        </tr>
      </thead>
      <tbody>
        {this.state.personData.map((Row, idx) => (
          <tr key={Row.id}>
            <td>{idx + 1}</td>
            <td>{Row.name}</td>
            <td>{Row.age}</td>
            <td>{Row.addr}</td>
            <td>
              {" "}
              <DropDownButton id={Row.id} onDelete={this.onDelete} />{" "}
            </td>
          </tr>
        ))}
      </tbody>
    </table>
  );
};

And then in your DropDownButton you need to call this onDelete callback

handleDelete () {
  console.log("ID " + this.props.id);

  fetch("http://localhost/person/" + this.props.id, {
    method: "DELETE",
    headers: {
      "Access-Control-Allow-Origin": "*",
      "Access-Control-Allow-Headers": "Content-Type"
    }
  })
    .catch(error => console.log("Error:", error))
    .then(response => {
      // call the passed in onDelete method here with the cooresponding id
      this.props.onDelete(this.props.id);
      console.log("Success:", response)
    });
}
render () {
  // ...
}

when this onDelete callback is called, the state in the parent component will change, causing it to rerender the list with only the items in the new list

Joshua Wootonn
  • 1,041
  • 7
  • 9
0

I have a problem that may be related to what is discussed in this thread. After adding or editing a column I am changing the color of the cells, but when I delete a row even though the state has changed the the cell colors remain intact until I change the pagination.

Edited

Following stackOverflow's behavioral steps, create a separate thread to address the problem. In case someone has the same problem you can see the solution to the problem in this thread.

Xabi
  • 95
  • 8