Error with . splice, is removing the first element and not specified

Asked

Viewed 152 times

0

I have a problem trying to remove a specific element from AsyncStorage, is always being removed first element.

Adding element:

  async function adicionar() {
    if (produto === '') {
      alert('Informe um item antes de prosseguir!');
      return;
    }
    if (valor === '' || valor === null) {
      setValor(0);
    } else {
      try {
        let lista = {
          id: Math.floor(Math.random() * 65536),
          produto,
          quantidade: parseInt(quantidade),
          valor: parseFloat(valor).toFixed(2).replace('.', ','),
          valorTotal: parseFloat(quantidade * valor)
            .toFixed(2)
            .replace('.', ','),
        };

        const data = (await AsyncStorage.getItem('items')) || '[]';
        let items = JSON.parse(data);
        //let items = [];
        items.push(lista);

        await AsyncStorage.setItem('items', JSON.stringify(items)).then(() => {
          setProduto('');
          setQuantidade('');
          setValor('');
          console.log(items);
        });
      } catch (error) {
        console.log(error);
      }
    }
  }

Loading the elements:

  async function getItems() {
    try {
      const lista = await AsyncStorage.getItem('items');
      const data = JSON.parse(lista);

      let total = data.reduce(
        (acc, objeto) => acc + parseFloat(objeto.valorTotal),
        0,
      );
      let totalQtd = data.reduce(
        (acc, objeto) => acc + parseFloat(objeto.quantidade),
        0,
      );
      setTotal(total);
      setTotalQtd(totalQtd);
      setData(data);
      console.log(lista);
    } catch (error) {
      console.log(error);
    }
  }

Removing the element:

 async function handleDelete(index) {
    try {

      const lista = await AsyncStorage.getItem('items');
      const data = JSON.parse(lista);

      data.splice(index, 1);
      await AsyncStorage.setItem('items', JSON.stringify(data));
     
     getItems();
      console.log(data);
    } catch (error) {
      console.log(error);
    }
  }

 async function deleteItem(item) {
 try {
  var index = data.filter((item) => item.id !== id);

  console.log('produto: ' + item.produto); // retorna o nome do produto referente ao id, por exemplo macarrão, ou seja o filter está funcionando.
  
  data.splice(index, 1); // mas ainda está removendo o primeiro item da lista

  AsyncStorage.setItem('items', JSON.stringify(data));
} catch (error) {
  console.log('error: ', error);
}}
  • What is the value of index? Where Voce uses the function handleDelete, What value did you pass to her? Are you removing the previous item you want to remove? It is not possible to understand the error without further details, but it may be because of the value of index.

  • My dear, I am calling the function through the Flatlist, created a button (<Touchableopacity onPress={() => handleDelete(item)}>) that calls the function. It is said to delete an item from the list, but remove the previous one.

  • I don’t know if it makes a difference, but when you add items, the array is saved as follows: [{"id":15321,"product":"rice","quantity":2,"value":"3,00","valueTotal":"6,00"},{"id":16715,"product":"feijao","quantity":2,"value":"1,00","valueTotal":"2,00"},{"id":39909,"product":"macarrao","quantity":3,"value":"2,00"valueTotal":"6,00"}]

  • I added the rice first, then the beans and finally the pasta. When I say delete the beans, the rice is removed.

  • 1

    I understood then the value of index would then, for example, this object {"id":16846,"produto":"arroz","quantidade":1,"valor":"2,00","valorTotal":"NaN"}? 'Cause if it is, it’s gonna be a mistake, because index has to be a number.

  • So I’m creating array incorrectly, this is it?

  • My dear, I thought the index was the id of each object.

  • No, but if the structure that Voce showed has a id unico, Voce could filter array items by id with the method filter(). This would be, in my opinion, the best way to remove a specific element from an array.

  • Got it!!! Blz, I’m going to try it here. It was totally worth it!

  • @Wanderaugusto Index (or index) is the position of each element in the array, starting at 0. For example, [a, b, c, d , e, f, g] have respectively the indexes [0, 1, 2, 3, 4, 5, 6].

  • Right @Rafaeltavares, but still not understood why is removing the last item added in the list. As you said the index is the position of each element in the array, I am trying to remove for example the index element 2, which in the example above refers to "noodles", but is removing the index 0 which is "rice". Did you manage to discover the error? Expensive something so simple that I stopped, has several days and nothing. I studied in these days a lot about array but without success.

  • @Cmtecardeal has already explained that you are not passing the index. And if an invalid index is passed (your case), the splice will start at the beginning of the array, so first item is removed. By the way, I don’t understand why in the question you say last item and here in the commentary is the first item

  • mal aí @Rafaeltavares, I misspelled the question. It is the Cmtecardeal directed to use the filter but also could not. I’m reviewing the way I created the array.

Show 8 more comments

1 answer

3

As has already been said in the comments, the problem is that the splice should receive the element index (its position in the array), not the element itself. When you pass an invalid index, the splice will start from the beginning of the array, and so the first element is removed. For example:

const arr = ['a', 'b', 'c', 'd', 'e'];
arr.splice('c', 1);
console.log(arr); // ['b', 'c', 'd', 'e'];

If you know which element to remove, but don’t know its content, you can use one of the following functions:

  • indexOf for primitive primitive values

const arr = ['a', 'b', 'c', 'd', 'e'];
const indexC = arr.indexOf('c');
arr.splice(indexC, 1);
console.log(arr); // ['a', 'b', 'd', 'e'];

const arr = [{ letra: 'a' }, { letra: 'b' }, { letra: 'c' }, { letra: 'd' }];
const indexC = arr.findIndex(objeto => objeto.letra === 'c');
arr.splice(indexC, 1);
console.log(arr); // [[{ letra: 'a' }, { letra: 'b' }, { letra: 'd' }];


Another option is to make use of filter, as stated in the comments, it will return you a new array. Note that here in addition to a new array being created, the original array is not modified and the filter must go through all elements of the array.

The new array will contain all the elements you pass as true by the condition of filter:

const arr = [{ letra: 'a' }, { letra: 'b' }, { letra: 'c' }, { letra: 'd' }];
const resultado = arr.filter(objeto => objeto.letra !== 'c');
console.log(resultado); // [[{ letra: 'a' }, { letra: 'b' }, { letra: 'd' }];


Your code also has other problems, for example;

  • In the handleDelete you don’t get the list of the state, but on AsyncStorage again.
  • In the handleDelete you call getItems searching for the updated list on AsyncStorage instead of simply updating the states (you already know what has changed).
  • In the handleDelete you call it index and works hoping to receive an index, but calls the function by passing an array item, not its index.
  • In the getItems is using two .reduce in the same array. It could use only one that returns an object with the desired values, thus traversing the array only once.
  • Thanks Rafael, you helped me a lot, I’ll go over everything you said. I call the function getItems was with the idea of rerenderizar the items because after that excluded the total value of the list and total quantity and did not update the state, in this way I thought better, so would be forcing the update and rerenderiza the values.

  • You can put the logic of updating the state and totals into a separate function that gets the list. So you call this function both within the getItems how much inside the handleDelete and you don’t need to read from AsyncStorage again.

  • Better explaining: I call the function getItems, because after I delete, I was not updating the states of "total value of the list" and also the "quantity of items", so this way I thought better, so I would be forcing the update and rerenderizaria these values.

  • Got it!!!! I’ll check out this idea of yours too, vlw!!!

  • Guys, if you can check one more: I changed the code to: async Function deleteItem(item) { Try { var index = data.filter((item) => item.id !== id); console.log('product: ' + item.product); // returns the product name for the id, for example macaroni, i.e., the filter is working. data.splice(index, 1); // but is still removing the first item from the list Asyncstorage.setItem('items', JSON.stringify(data)); } catch (error) { console.log('error: ', error); }} Any more personal ideas? Thank you.

  • Leave it like this: async Function deleteItem(item) { Try { const result = data.filter((item) => item.id !== item); console.log(result); Asyncstorage.setItem('items', JSON.stringify(data)); } catch (error) { console.log('error: ', error); } } is returning all elements, it seems it is not filtering.

  • @Wanderaugusto you need to pay attention to what you are doing. This answer has several different examples of how to deal with the situation. Look what you’re doing in the filter: (item) => item.id !== item. Besides having two variables with the same name item (received as a function parameter deleteItem and that of filter), is comparing a id with an entire object, it won’t work like this...

  • 1

    I got Rafael, thanks for the support! Fiz isto: const lista = JSON.parse(await AsyncStorage.getItem('items'));&#xA;&#xA; const novaLista = lista.filter((produto) => produto.id !== item.id);&#xA; await AsyncStorage.setItem('items', JSON.stringify(novaLista)); ---- Agora vou refatorar, correct function names and change variables.

Show 3 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.