Updating react state in array?

Adding to a list of favorites for a pokedex, this is what I have:

  const addFavorite = (id) => {
    if (!favorites.length) {
      setFavorites([id])
    } else {
      const newList = favorites.map(favPokemonId => {
        return favPokemonId !== id ? [ ...favorites, id ] : favPokemonId;
      });
  
      setFavorites(newList);
    }
  };

It keeps creating a nested array within the original array. What can I do to fix this?

The .map() callback is executed on every item in the array, so when it returns [...favorites, id] it is replacing that array item with an array.

1 Like

How do I grab the rest of the state? Just do that when I set the state?

I don’t understand the question.

I need to grab the rest of the id’s from the state to throw it into an array of id’s.

EDIT: Didn’t know if it would be like:

setFavorites([...favorites, newList])

What are you trying to do in your map function?

Add favorites. If I toggle a button it runs this function and adds an id to the array, ex: [3].

If I click on id:3 again, it won’t add to the array, but if I click on id:4 or 10 or 56, it will add it to the array like so:

[3, 56]

EDIT: For further clarification, it is mapping through that array in the state and will check if the one you clicked on does not exist, then add it to the array. For some reason the spread operator is giving me way more issues than I thought it would in this particular context.

If you just need to add a value to an array if it isn’t already in the array, then you do not want to use a .map() method.

What would be ideal here? It’s more than just adding, but also editing.

What are you editing? You only described adding.

The .map() method is for changing all the values in an array. For example: you would use .map() if you wanted to convert all strings in an array to lowercase or wanted to add 10 to all the numbers.

If you only need to add an item to an array if it isn’t in the array already, you just need an if statement and a .push().

1 Like

It’s a toggle of favorites. If the id is in the array, and I click on that same id to unfavorite it, I would expect it to be deleted from the array. So more of adding and deleting.

Ok. So that should probably be an if/else. .map() doesn’t add or remove items.

What would be your recommendation then?

An if/else statement, depending on whether the id is found in the array.

Went along this path, but getting some errors. Gotta keep digging through:

  const addFavorite = (id) => {
    let newList = [];
    const foundId = favorites.find((foundId) => foundId === id);

    if (!foundId) {
      newList.push(id);
    } else {
      let index = newList.indexOf(foundId);
      newList.splice(index, 1);
    }

    setFavorites(newList);
  };

Thought maybe a filter could work instead of index, ahh idk:

  const addFavorite = (id) => {
    let newList = [];
    const foundId = favorites.find((foundId) => foundId === id);

    if (!foundId) {
      newList.push(id);
    } else {
      newList.filter(pokemonId => pokemonId !== id)
    }

    setFavorites(newList);
  };

This is pushing the id to a brand new array that does not contain the previous favorites.

Why use find and then indexOf? Why not only use indexOf?

newList is an empty array.

Now I’m really confused. It needs to be an empty array at first. Which is why I thought I needed the spread operator if taking in the previous state. UGH

It may need to be an empty array at first, but you can’t delete an item from an empty array. If you add one item to an empty array, you have an array containing one item. What are you doing with the rest of your favorites?

The desired state is to have this array of favorite ID’s and then store that whole array in localstorage. I’m just trying to get this to work first lol