Omeed2 Omeed2 - 2 months ago 10
React JSX Question

How to loop inside a react const variable in the render method

I have a mapped const variable which I use to inject to my return in the render method. My issue is now, the object I am mapping, has a collection of objects itself. I would like to loop through each one and add jsx syntax in. This is what I have:



const tasks = this.state.tasks.map((task) => {
var editable = this.state.editableTasks.filter(id => id === task.Id).length > 0;
return (
<li key={task.Id} className="list-group-item" style={{minHeight: '50px'}}>
<div className="pull-left" style={{width: '50%'}}>
{editable ? <input type="text" /> : <span>{task.Name}</span>}
</div>
<div className="pull-right" style={{marginTop: '-5px', width: '50%'}}>
<div className="pull-right">
<button className="btn btn-default" onClick={() => {this.AddSubTask(task.Id)}}>Add</button>
<button className="btn btn-default" onClick={() => { this.EditTask(task.Id)}}>{editable ? 'Save' : 'Edit'}</button>
</div>
</div>
</li>

//What I have currently tried:
//for(var i = 0; i < task.SubTasks.length; i++) {
//<ul>
//<li>
//...etc
//</li>
//</ul>
//}

//{task.SubTasks.map((subtask) => {
//<ul>
//<li>
//...etc
//</li>
//</ul>
//)};
);
});
return (
<div className="table-wrapper">
<div className="task-container">
<h3>{this.props.rowName}</h3>
</div>
<ul id="tasksContainer">
{tasks}
<li className="list-group-item list-group-item-last"><input type="button" value="Add Task" onClick={this.createTask.bind(this)} className="btn btn-success btn-override" /></li>
</ul>
</div>

);





I do apologize for the formatting, couldn't quite get it right. Anyways, so in the const task = declaration, I would like to loop through each task.SubTasks (the collection OF the indexed collection) and add in another unordered list.

I have tried simply writing a for loop but it didn't work, and also trying to write another mapped function, which didn't work either. Is this doable?

Answer

Another map should work.. the for loop could work if you create an empty array first and push components to it.

const subTaskComponents = []
for (var i = 0; i < task.SubTasks.length; i++) {
  subTaskComponents.push(
    <ul key={task.SubTasks[i].id>
      <li>..</li>
    </ul>
  )
}

map is a nicer solution though

const subTaskComponents = task.SubTasks.map(subTask =>
  <ul key={subTask.id}>
    <li>..</li>
  </ul>
)

Then in either case you can use it the same way you have with tasks inside render:

render() {
  const tasks = this.state.tasks.map((task) => {
    const subTaskComponents = task.SubTasks.map(subTask =>
      <ul key={subTask.id}>
        <li>..</li>
      </ul>
    )

    return (
      <div>{subTaskComponents}</div>
    )
  }

  return (
    <div>{tasks}</div>
  )
}