0

I have a table being populated by rows mapped by an array. I want to have an expanded view (or div) of data when I click a button in that row. I run into an issue where I can't have two table rows in the same .map iteration.

I'm thinking there are multiple ways of doing this.

I could swap a table row for a row that spans the width of the table with a div inside of it, using an if statement tied to the id the of the event I want to expand.

I could jquery a div underneath the table row (not sure how to accomplish this).

<tbody className={loading}>
      {this.state.events.map((event, id) => 
        <tr key={event.id}>
          <td>{event.data || ' '}</td>
          <td>{event.otherData}</td>
          <td><TimeStamp time={event.timestamp} /></td>
          <td><button onClick={() => this.onShowInfo(event)}>
            <i className="fa fa-search-plus" /></button></td>
        </tr>
      )}
    </tbody>

JSX makes it impossible to have two rows rendered in a map function

Fred Chapman
  • 133
  • 1
  • 10

3 Answers3

0

The soulution for your problem can be found here: How to return multiple lines JSX in another return statement in React?

Use this example:

{[1,2,3].map(function (n) {
  return ([
    <h3></h3>, // note the comma
    <p></p>
  ]);
})}
Community
  • 1
  • 1
0

Although you're right taht you can't RETURN more than one parent tr in your logic block, you can have multiple blocks so this would work just fine:

<tbody className={loading}>
      {this.state.events.map((event, id) => 
        <tr key={event.id}>
          <td>{event.data || ' '}</td>
          <td>{event.otherData}</td>
          <td><TimeStamp time={event.timestamp} /></td>
          <td><button onClick={() => this.onShowInfo(event)}>
            <i className="fa fa-search-plus" /></button></td>
        </tr>
      )}
      {this.returnSomeOtherTr()}
    </tbody>

Where returnSomeOtherTr is a function that returns some other <tr>.

ZekeDroid
  • 7,089
  • 5
  • 33
  • 59
  • but I want to be able to render a row under a specific row to show more info about that row. your example just renders a separate row underneath the rest of the mapped rows – Fred Chapman Apr 17 '16 at 18:25
  • gotcha. what if instead of "swapping" trs you just updated it in your map of events? you could have a `processedEvents` array that had the "expanded" tr in place of the non expanded one. What is your current thought which JSX stops you from executing? – ZekeDroid Apr 17 '16 at 19:02
0

So instead of mapping through the array of events, I pushed each event into an array with a for loop. when the event that I wanted the details of came up, my for loop would push an additional row that occupied the entire span (through colSpan) so that I would have the appropriate space to work with.

eventRows(events){
  var eventsArray = []

  for (var ev of events) {
    eventsArray.push(
      <tr key={ev.id}>
      </tr>
    )
    if(ev.id === this.state.showInfo.id) {
      eventsArray.push(
        <tr>
          <td colSpan='5'>
          </td>
        </tr>
      )
    }
  }
}
Fred Chapman
  • 133
  • 1
  • 10