1

I am currently trying to learn react by building a simple app that works with a JSON array by calling a certain API. I would then like to show the results of the array in a table and have the ability to click one of the rows and get the data from that row to update another part of the page.

I have successfully called the API and am showing the correct data in the table but I am struggling to figure out how to show the data after the click in another part of the page. I created a click handler event and can log information to the console but cant figure out how I would show this data on the page for the relevant row that is clicked.

So I currently have this in my page:

<div class="container"></div>

<script type="text/jsx">

    var ShowData = React.createClass({

          getInitialState: function() {
            return { data: [] };
          },

          componentDidMount: function() {
            $.get(this.props.source, function(data) {
              if (this.isMounted()) {
                this.setState({
                    data: data
                });
              }
            }.bind(this));
          },

          handleClick: function(i) {
            console.log('You clicked: ' + this.state.data[i].event + this.state.data[i].name);
          },

          render: function() {
            var self = this;
            return (
                <table className="m-table">
                    <thead>
                            <tr>
                                <th>Event</th>
                                <th>Name</th>
                            </tr>
                        </thead>
                    <tbody>
                    {this.state.data.map(function(type, i){
                   return (
                        <tr>
                            <td title="Type" onClick={self.handleClick.bind(this, i)} key={i}>{type.event}</td>
                            <td title="Type">{type.name}</td>
                        </tr>
                    )
                })}

                        </tbody>
                    </table>
            );
          }

        });

  React.render(
          <ShowData source="url of api" />,
          document.getElementById('container')
        );

</script>

Below this script is another container that I would like to show the results when the table row is clicked.

So to summarize, I want to display the data from the API call in a table, upon clicking on one of the table rows I want to take the table row data and format it in another container on the page.

1 Answer 1

1

I'd move both the table-component and the display area-component into a parent component that has the responsibility of managing state. The parent component will pass a callback for handling row clicks down to the table, something along the lines of the below edits to your code example. (Heads-up: haven't slept in the past 40+ hours when writing this, due to travel..)

<div class="container"></div>

<script type="text/jsx">

    var TableComponent = React.createClass({   
          handleClick: function(i) {
             this.props.clickHandler(i);
          },

          render: function() {
            var self = this;
            return (
                <table className="m-table">
                    <thead>
                            <tr>
                                <th>Event</th>
                                <th>Name</th>
                            </tr>
                        </thead>
                    <tbody>
                    {this.props.data.map(function(type, i){
                   return (
                        <tr>
                            <td title="Type" onClick={self.handleClick.bind(this, i)} key={i}>{type.event}</td>
                            <td title="Type">{type.name}</td>
                        </tr>
                    )
                })}

                        </tbody>
                    </table>
            );
          }

        });

  var DetailsArea = React.createClass({
      render: function() {
          var rowDetails = this.props.rowDetails;

          return <div>{rowDetails.name}</div>;
      }
  });

  var ParentComponent = React.createClass({
      getInitialState: function() {
          return {data: []};
      },

      componentDidMount: function() {
          $.get(this.props.source, function(data) {
            if (this.isMounted()) {
              this.setState({
                  data: data
              });
            }
          }.bind(this));
       },

       rowClickHandler: function(rowIndex) {
           this.setState({selectedRow: rowIndex});
       },

       render: function() {
           var tableData = this.state.data;
           return (
               <TableComponent data={tableData} clickHandler={rowClickHandler} />
               <DetailsArea rowDetails={tableData[this.state.selectedRow]} />
       }
  });

  React.render(
          <ParentComponent source="url of api" />,
          document.getElementById('container')
        );

</script>
Sign up to request clarification or add additional context in comments.

2 Comments

I feel that it's important to point out that if you do this, you'll create a new function for each call to render which in turn will invalidate your DOM because the function reference changed. This will cause React to remove/add all onClick event listeners. Let the event bubble instead a catch it higher up in the DOM, the part of the DOM that doesn't necessarily change.
I just learned that React subscribes to event handlers in a different manner. So it's not as bad as I originally thought. You can read more about it here (facebook.github.io/react/docs/…) but you should really catch the event higher up in your DOM.

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.