How can I ensure an id remains defined after changes to the array?

I'm trying to create an app that can add, edit, and delete "facts" in a table, adapted from an example to-do list program. I use an id number to create a unique key for each td item, and attach it to a variable called todoItem. This is all well and good. Adding and editing items works perfectly well.

However, when I try to delete an item (by splicing out a specific index in my array), todoItem becomes undefined. Something in the deletion function is also deleting the todoItem variable. This means that after deleting an item, I can't add more items and get a TypeError: Cannot read property 'id' of undefined error if I try to add one. There's no reference to todoItem in my deletion function, so I don't understand how it's getting deleted.

const handleDelete = (id) => {
 const deleteList = todos.map((oneTodo) => {
   if (oneTodo.id === id) {
     console.log("id "+id);
     oneTodo = todos.splice(id, 1);
   }
   return oneTodo;
 });
 console.log(deleteList);
 setTodos(deleteList);
 console.log("todo, id:"+todo, id);
 console.log("length: "+todos.length);
};

I am also getting an Warning: Each child in a list should have a unique "key" prop. Check the render method of FactsHandler. error after running the deletion function (and not the add/edit functions). I suspect this is caused by the former problem, as I use the todoItem.id to define a key for each item; if it's missing, a key can't be defined.

The code I'm writing is quite lengthy and a bit messy, so I'm adding the full code as pastebins. I'm thinking it could possibly be something else in my program, but I don't know where or what that would be. Any help would be appreciated. I've poured over this code for several hours this evening and haven't gotten anywhere.

FactsHandler (main function) https://pastebin.com/UzUpNyjK

Item (item component) https://pastebin.com/fncrRfDA

4 answers

  • answered 2021-01-11 05:20 Kalhan.Toress

    try this out

    const handleDelete = (id) => {
        const index = todos.indexOf(todo => todo.id === id);
        if (index !== -1) {
            todos.splice(index, 1);
            setTodos([...todos]);
        }    
    };
    

  • answered 2021-01-11 05:20 Mohammad Faisal

    javascript array.map() doesn't work the way you used it. you are supposed to return a new item for each element of the array

    YOu can use javascript array.filter() method for this purpose

    const deleteList = todos.filter((oneTodo) => oneTodo.id !== id );
    

  • answered 2021-01-11 05:23 Alex Mckay

    In my opinion you are using the wrong list operator (map) when you should be using filter:

    const list = [
      { id: "apple", label: "Apple" },
      { id: "banana", label: "Banana" }
    ];
    const deleteItem = (itemId) => list.filter(({ id }) => id !== itemId);
    deleteItem("apple") // => [{id: 'banana', label: 'Banana'}]
    

  • answered 2021-01-11 05:42 Parth Mansata

    There are many ways to properly remove the object from the array. A reference of the same can be taken from here. Easiest ways, I found are:

    1. Using conditional for loop,
    2. Using Array.splice()

    Ex.

    let todos = [{
        "id": 1,
        "name": "ABC"
    }, {
        "id": 2,
        "name": "DEF"
    }, {
        "id": 3,
        "name": "GHI"
    },]; 
    const id = 1;
    
    // Approach 1
    for(let i =0; i < todos.length; i++){
       if(todos[i].id === id){
           todos.splice(i, 1);
           break;
       }
    }
    
    // Approach 2
    todos = todos.filter((oneTodo) => oneTodo.id !== id );
    
    console.log('Updated todos:', todos);