2

I have to create and push a nested array of objects to an array.

My code snippet with an array of recipes in the file called recipes.js would look like this:

const createRecipe = () => {
    const id = uuidv4()
 
    recipes.push({
        id: id,
        title: '',
        body: '',
        ingredients: []
    })
    saveRecipe()
 
    return id
}

Then, in the file ingredients.js I imported the function createRecipe() and try to push the ingredients to the recipe array like this:

const createIngredients = (recipes, text) => {
    recipes.ingredients.push({
        id: uuidv4(),
        text,
        completed: false
    })
    saveIngredients()
}

but my code doesn't work, I get an error

what is the right way to push this nested array of ingredients to the recipes array?

1
  • what is the error? Commented Sep 19, 2020 at 8:05

4 Answers 4

2

As @DarkSigma points out the recipes is an array, which is the source of the error.

To build out on what has already been said, here's some more detail:

recipes.push({
  id: id,
  title: '',
  body: '',
  ingredients: []
})

produces a data structure of:

[{id: 1, title: '', body: '', ingredients: []}, {id: 2, title: '', body: '', ingredients: [] /* etc. */}]

So for each item in recipes, the ingredients is another list of items.

When we get to adding some new ingredients like:

recipes.ingredients.push({
  id: uuidv4(),
  text,
  completed: false
})

the error is recipes.ingredients because recipes is an array so we would have to find the recipe that matched the ingredients we were adding.

Hence, your function would need to do something like:

const createIngredients = (recipes, recipeId , text) => {
    // Look up the recipe for the given id
    const foundRecipeById = recipes.find(x => x.id === recipeId);
    if (foundRecipeById) {
        // Now add the ingredients to the found recipe
        foundRecipeById.ingredients.push({
            id: uuidv4(),
            text,
            completed: false
        })
        saveIngredients()
    }
    else {
        // Do something intelligent if the recipe is not found
    }
}

This way we are looking up/matching the recipe with the ingredients

Sign up to request clarification or add additional context in comments.

3 Comments

This error I am getting: ingredients.js:26 Uncaught TypeError: Cannot read property 'push' of undefined
hmmm, I don't get that error, it works as expected ¯_(ツ)_/¯ I did notice a copy-paste error I'll fix above, but your code looks "fine" for that error.
hey thanks for your help! unfortunately, still not working!
0

recipes is an array of objects. Each of those objects has the ingredients field, which is itself an array.

recipesitself does not have an ingredients field.

Therefore, you need to loop through the elements of recipes. For each recipe object, push many ingredients into its ingredients array.

2 Comments

forEach() or map()?
It would depend on what you are trying to do. forEach will loop, map returns a transformation of the original leaving the original intact. If you are trying to do this to all the elements (forEach), if you are trying to find a specific item (find), if you want to transform each element (map)
0

Arrays are lists of objects and these objects can be as complicated as you like. I prefer to create custom objects to hold all of the values that I push onto an array, but that is optional. I do this to ensure that the structure of each entry in the array is exactly the same.

If an object needs to hold an array itself - as in your ingredients for a recipe - you need to build that child array and add it to the main object before adding that main object into the main array (you can add it later, but that's more complicated!).

Here is an example of what I mean:

// create a recipe object
let recipe = {
  id: "",
  name: "",
  ingredients: ""
}
// create an ingredient object with a constructor to make it easier to populate
function ingredient (recipeid, name, quantity){
  this.recipeid = recipeid;
  this.name = name;
  this.quantity = quantity;
}
// create a recipes array and truncate it (it always seems to start with a blank entry)
let recipes = [];
recipes.length = 0;

// Now create a recipe
function addRecipe() {
  let thisrecipe = Object.create(recipe);
  thisrecipe.id = 1;
  thisrecipe.name = "Scrambled eggs";
  // create a dummy array for the ingredients
  let ings = [];
  ings.length = 0;
  // create a new ingredient object for each ingredient
  // and push that onto the dummy array
  let ing = new ingredient(thisrecipe.id, "eggs", "2");
  ings.push(ing);
  ing = new ingredient(thisrecipe.id, "cream", "6 tbps");
  ings.push(ing);
  ing = new ingredient(thisrecipe.id, "butter", "1 knob");
  ings.push(ing);
  // once all ingredients have been added onto the dummy array, update the recipe object's ingredients property
  thisrecipe.ingredients = ings;
  // finally, push the completed recipe onto the recipes array
  recipes.push(thisrecipe);
}

addRecipe();
console.log(recipes);

Obviously, this is all hard coded for one recipe and three ingredients - but, hopefully, it should give you the principles you need to build up a complete recipes array

1 Comment

There are two push() statements: ings.push(ing) and recipes.push(thisrecipe). The first is required to add the list of ingredients to the recipe object. If the recipe object already exists on an array then you don't need the second push() as you are updating that recipe object directly.
0

I think that the push() function is operating on the property and not its value. If you add in a few extra lines:

const createIngredients = (recipes, recipeId , text) => {
    // Look up the recipe for the given id
    const foundRecipeById = recipes.find(x => x.id === recipeId);
    if (foundRecipeById) {
        // Now add the ingredients to the found recipe
        let ings = foundRecipeById.ingredients;
        ings.push({
            id: uuidv4(),
            text,
            completed: false
        })
        foundRecipeById.ingredients = ings;
        saveIngredients()
    }
    else {
        // Do something intelligent if the recipe is not found
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.