Home > Software design >  JavaScript map inside map
JavaScript map inside map

Time:03-30

I'm currently building a budgeting application with React and JavaScript. Right now I'm able to print a table of costs like shown below.

Name Budget Used $ Used % Available
Food 300 300 100 0
Streaming services 600 600 100 0

Here is the code where I fetch data and map through each item to the table:

     <tbody>
      {expenses.budgetedAmounts
        .sort((a, b) => {
          return a.department < b.department;
        })
        .map((item, index) => (
          <tr
            key={index}
          >

            <td>
              {item.name}
            </td>

            <td>
              {item.budgetedExpense}
            </td>

            <td>
              {item.actualExpense} 
            </td>

            <td>
              {item.percentageUsed} 
            </td>

            <td>
              {item.availableExpense}
            </td>
          </tr>
        ))}
    </tbody>

I would also like to add sub-items to the table that show what the budget of each item consist of. For example, the budget set for food consists of french fries and apples.

Name Budget Used $ Used % Available
Food 300 300 100 0
• French fries 150
• Apples 150
Streaming services 600 600 100 0
• Netflix 300
• Disney 300

Subitems are also in array which can be accessed via "item". I'm thinking that I could just add another loop after the first map method:

              {item.nestedItems.map((nested, secondIndex) =>              
              )}

And I could access items like this:

{nested.name} and {nested.price}

Data is fetched correctly, but I can't seem to figure out where to place nested loop in the code and how to achieve wanted table structure. I know this is probably hard question to answer without being able to try the code, but any ideas to help would be just great!

CodePudding user response:

You could first flatten your array, and then do that final map, taking some precautions that undefined properties do not result in undefined outputs:

    <tbody>
      {expenses.budgetedAmounts
        .sort((a, b) => a.department < b.department)
        .flatMap(a => [a, ...a.nestedItems])
        .map((item, index) => (
          <tr key={index}>
            <td>{item.name}</td>
            <td>{item.budgetedExpense ?? item.price}</td>
            <td>{item.actualExpense ?? ""}</td>
            <td>{item.percentageUsed ?? ""}</td>
            <td>{item.availableExpense ?? ""}</td>
          </tr>
        ))}
    </tbody>

Note that the index now no longer corresponds with the original index in the non-flattened array. I assumed it just served as a unique reference, but if not, you may want to add some code to still have access to the original index.

CodePudding user response:

The simplest way to do this do exactly what you want to. Write another map right after the tag in the first map to render sub-item rows. Something like this:

  <tbody>
  {expenses.budgetedAmounts
    .sort((a, b) => {
      return a.department < b.department;
    })
    .map((item, index) => (
      <><tr
        key={index}
      >

        <td>
          {item.name}
        </td>

        <td>
          {item.budgetedExpense}
        </td>

        <td>
          {item.actualExpense} 
        </td>

        <td>
          {item.percentageUsed} 
        </td>

        <td>
          {item.availableExpense}
        </td>
      </tr>
      {item.nestedItems.map((nested, secondIndex) =>   <tr>
        <td> {nested.name}</td>  <td> {nested.price} </td>

      </tr>)}</>
    ))}
</tbody>

CodePudding user response:

Try this

<tbody>
    { budgetedAmounts.map((item,index)=>{
      return(
      <> 
      <tr key={index   "b"}> 
         <td>{item.name}</td>
         <td>{item.budgetedExpense}</td>
         <td>{item.actualExpense}</td>
         <td>{item.percentageUsed}</td>
         <td>{item.availableExpense}</td>
      </tr>
      { item.subItem && item.subItem.map((subItem,subIndex)=>{
          return(
             <tr key={item.id   " __ " subIndex}>
             <td>{subItem.name}</td>
             <td>{subItem.budgetedExpense}</td>
             <td>{subItem.actualExpense}</td>
             <td>{subItem.percentageUsed}</td>
             <td>{subItem.availableExpense}</td>
             </tr>
          )
       })
      }
     </>
   )
 })
}
</tbody>
  • Related