1

I have two components, the parent is called Layout and the child Report. In Report I have a table that loops through and renders a list of car accidents. I have a handler - handleIncidentReport in Report that calls a function in Layout to update this.state.obds (car messages) which then obviously updates the child Report.

My question is what is the proper ReactJS way to have it so only the row clicked has its {this.props.incident_report} updated, and not the other dynamically created rows with the same yield statement (not sure of the correct terminology).

I'm less than a week into ReactJS and I know I could hack it together but I want to know the proper way.

Here is a chunk of the two files -

Report

handleIncidentReport: function(e) {
  var accident_id = $(e.target).closest('tr').data('accident-id')
  this.props.changeIncidentReport(e, accident_id)
},
render: function() {
  var self = this;
  var accidents = [];

  for (var i = 0; i < this.props.accidents.length; i++) {
    var incident = this.props.accidents[i];

    accidents.push([
      <tr key={i} onClick={self.handleIncidentReport} data-accident-id={incident.id} >
        <td>{incident.owner.first_name} {incident.owner.last_name}</td>
        <td>{incident.car.title}</td>
        <td>{moment(incident.created_at).format("MMM D, YYYY - hh:mm A")}</td>
      </tr>,
      <tr className="incident-report">
        <td colSpan="3">
          <Obds obds={this.props.incident_report} />
        </td>
      </tr>
    ]);

  };

  return (
    <div className="report">
      <table className="table">
        <thead>
          <tr>
            <th>Name</th>
            <th>Car</th>
            <th>Date</th>
          </tr>
        </thead>
        <tbody>
          {accidents}
        </tbody>
      </table>
    </div>
  );
}

Layout

changeIncidentReport: function(e, accident_id) {
  var $tr = $(e.target).closest('tr');

  $.ajax({
    method: "GET",
    data: {accident_id},
    url: "/superadmin/emergency_analysis/get_incident",
    datatype: 'jsonp'
  }).success(function(incident){
    this.setState({
      incident_report: incident
    });
  }.bind(this));
},
Ryan Grush
  • 2,076
  • 3
  • 37
  • 64
  • if i understand correctly, you want to update the props of the child that was clicked? if so, then why do it through the parent? why not do it directly from the child? – FuzzyTree Jun 03 '16 at 23:33
  • I did it through the parent because there is a sibling element that needs to have the updated `incident` passed to it as well. But I would love to know how to solve the problem from within the same element as well if thats easier. – Ryan Grush Jun 06 '16 at 15:19

1 Answers1

0

You should make it so that handleIncidentReport returns a function that is configured (through closures) with the index of each of the rows, something like:

handleIncidentReport: function(accident_id) {
  return function(e) {
    this.props.changeIncidentReport(e, accident_id)
  }
},

(If you aren't sure how closures work you should check out this excellent post: How do JavaScript closures work?)

Then update your render to use

  <tr key={i} onClick={self.handleIncidentReport(i)} data-accident-id={incident.id} >

and each of the rows will have a unique handler all of their own that will be called when they're clicked on.

This should also get rid of some of that jQuery which figures out which accident_id was clicked on too.

Community
  • 1
  • 1
Ben Hare
  • 4,365
  • 5
  • 27
  • 44
  • I've heard of closures before but admittedly never know when to use them. I'll try this approach but this would still update every `{accidents}` in my Report class, no? That's mainly what I'm trying to avoid. Obviously I can hide the other `{accidents}` that get updated with jQuery but I wanted to see if there was a better way first. – Ryan Grush Jun 06 '16 at 15:31
  • 1
    Check out closures and you'll see why it shouldn't update all of them :) – Ben Hare Jun 06 '16 at 15:54
  • Its still updating all the children elements unfortunately. – Ryan Grush Jun 06 '16 at 18:40
  • Here is the latest https://jsfiddle.net/nosfan1019/69z2wepo/44715/. I'll try to update it with some actual data. – Ryan Grush Jun 06 '16 at 19:11