skip to Main Content

I’m just getting started on learning Reactjs in a laravel project, and I’m stuck on what should be a simple problem. I’ve passed some data that I want to present in a table organised by category and month. The data is an array of objects like this.

Budget

  • id
  • category
  • month
  • budget

Not all combinations will have data (eg only certain months are represented for a particular category) so I need to use external keys to ensure I have the right number of table cells. I have a separate list of categories that I can map, but I’m not sure how to handle looping through the months since JSX doesn’t seem to like my for loop.

export default function Budget({ auth, errors, categories, budget }) {
    return (
        <AuthenticatedLayout
            user={auth.user}
            header={<h2 className="font-semibold text-xl text-gray-800 leading-tight">Budget</h2>}
        >
            <Head title="Budget" />

            <div className="py-12">
                <div className="mx-auto sm:px-6 lg:px-8">
                    <div className="bg-white overflow-hidden shadow-sm sm:rounded-lg">
                        <div className="p-6 text-gray-900 flex flex-wrap">
                            <div>Category</div>
                            <div>Jan</div>
                            <div>Feb</div>
                            <div>Mar</div>
                            <div>Apr</div>
                            <div>May</div>
                            <div>Jun</div>
                            <div>Jul</div>
                            <div>Aug</div>
                            <div>Sep</div>
                            <div>Oct</div>
                            <div>Nov</div>
                            <div>Dec</div>
                            <div>Total</div>
                            <div>Previous Year</div>
                        </div>
                        {categories.map((category, index) => (
                            <div>
                                <div>{category.name}</div>
                                {for(let m = 1; m < 13; m++) {
                                    <div>{category[m].budget}</div>
                                }}
                            </div>
                        ))}
                    </div>
                </div>
            </div>
        </AuthenticatedLayout>
    );
}

This gives me an ‘expression expected’ error at the ‘for’. Other solutions I’ve seen suggest creating an array (1-12) to map, which seems like a poor solution. Do I need to create a component for the row so that I can use the ‘for’ before the return in each? That seems like a waste since I’ll never use it anywhere else in this or any other project.

What’s best practice in cases like this?

2

Answers


  1. The problem with your for loop is that you are using category as if it was an object and an array of objects. In this line <div>{category.name}</div> you are accessing a property which suggests an object but in this line <div>{category[m].budget}</div> you are accessing an element which suggests an array. I think you may have meant to reference an element of budget? <div>{category.budget[m]}</div>

    I would also question the range used in your for loop. JavaScript arrays are 0 based by default so unless you have overridden the default behavior it should probably be {for(let m = 0; m < 12; m++) {.

    If you fix the array issues would the suggestion made in the comments, to simply use another loop for the months, work?

    Login or Signup to reply.
  2. You can either make a function that creates that array:

    const getBudgets = (category) => {
      const budgets = [];
      for (let m = 1; m < 13; m++) {
        budgets.push(<div>{category[m].budget}</div>);
      }
      return budgets;
    };
    
    ...
    
    <>
      {categories.map((category, index) => (
        <div>
          <div>{category.name}</div>
          {getBudgets(category)}
        </div>
      ))}
    </>;
    

    Or use slice and map

    <>
      {categories.map((category, index) => (
        <div>
          <div>{category.name}</div>
          {category.slice(0, 13).map((cat) => (
            <div>{cat.budget}</div>
          ))}
        </div>
      ))}
    </>;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search