Isabel GM
Isabel GM

Reputation: 61

react component nested array of objects

I am new to react and I am having some trouble mapping nested array of objects in my app as it comes as undefined.

This is my api response which is an array of recipes.

const recipeMock = [
{
    "ingredientsInfo": [
        {
            "ingredientId": {
                "_id": "609e1325f5bbf3301d24102c",
                "name": "spaghetti squash",
            },
            "gramsPerIngredient": 301
        },
        {
            "ingredientId": {
                "_id": "609e1325f5bbf3301d24102b",
                "name": "spaghetti squash",
            },
            "gramsPerIngredient": 47
        },
    ],
    "_id": "609e1326f5bbf3301d241242",
    "name": "pain de mie",
    "gramsPerRecipe": 223,
    "elabTime": 20,
    "carbs": 201,
    "proteins": 10,
    "calories": 605,
        "instructions": "hi",
        "picture": "https://unsplash.com/photos/ijlUGGnrZsI",
    },{...other recipes following same structure
}]

I have created a component which paints each recipe that is the following:

export default function RecipeCard({
  recipeId,
  recipeName,
  ingredientsInfo,
  elabTime,
  carbs,
  proteins,
  calories,
  instructions,
  picture,
  addRecipeToUser,
})

which in return renders a card. But trouble comes when mapping ingredientsInfo as follows:

   <div className="recipeCard_ingredients">
    <ul className="recipeCard_ingredients_list">
      {ingredientsInfo.map((ingredient, index) => (
        <li key={index}>
          <Link to={`/ingredients/${ingredient.ingredientId.name}`}>
            {ingredient.ingredientId.name}
          </Link>
          <p>{ingredient.gramsPerIngredient} grams</p>
        </li>
      ))}
    </ul>
  </div>

The console tells me "Cannot read property 'map' of undefined".

Upvotes: 1

Views: 260

Answers (3)

msalla
msalla

Reputation: 765

Firstly, the RecipeCard function mustn't receive the recipeMock object as its parameters. In React, function parameters are used to pass props from other components.

Secondly, you have to map over recipeMock before you can access ingredientsInfo, since both are arrays. This means you have to nest two map functions like so:

const recipeMock = [
  {
    ingredientsInfo: [
      {
        ingredientId: {
          _id: "609e1325f5bbf3301d24102c",
          name: "spaghetti squash"
        },
        gramsPerIngredient: 301
      },
      {
        ingredientId: {
          _id: "609e1325f5bbf3301d24102b",
          name: "spaghetti squash"
        },
        gramsPerIngredient: 47
      }
    ],
    _id: "609e1326f5bbf3301d241242",
  }
];
const RecipeCard = () => {
  return recipeMock.map(({ ingredientsInfo, _id }) => (
    <div key={_id}>
      {ingredientsInfo.map(
        ({ gramsPerIngredient, ingredientId: { _id, name } }) => (
          <p key={_id}>
            {gramsPerIngredient}, {name}
          </p>
        )
      )}
    </div>
  ));
};

Here's a working demo in CodeSandbox.

Upvotes: 0

Bhojendra Rauniyar
Bhojendra Rauniyar

Reputation: 85573

Based on the error, and the mock, you have used:

<RecipeCard {...recipeMock} />

Instead of:

<RecipeCard {...recipeMock[0]} />

If you insist to use without index then make sure to map it first and then only map ingredientsInfo inside of it.

Upvotes: 0

Rashed Rahat
Rashed Rahat

Reputation: 2485

The error Cannot read property 'map' of undefined will be encountered if there is an error in the ingredientsInfo or ingredientsInfo there is no array.

Better put condition to check the the array like:

<div className="recipeCard_ingredients">
<ul className="recipeCard_ingredients_list">
  {ingredientsInfo && ingredientsInfo.map((ingredient, index) => (
    <li key={index}>
      <Link to={`/ingredients/${ingredient.ingredientId.name}`}>
        {ingredient.ingredientId.name}
      </Link>
      <p>{ingredient.gramsPerIngredient} grams</p>
    </li>
  ))}
</ul>
</div>

Upvotes: 1

Related Questions