'Delete an element from the array and update order

I have an array of objects in the state. The object has the order property. I need order prop for drag and drop. The list is sorted by order. Also, there is a function to remove an item from the list. How to correctly remove an element from an array with updating the order property?

  const deleteTodo = (id) => {

    //I tried using map but it doesn't work

    setTodos(todos.map((todo, index) => {
      if (todo.id !== id) {
        return { ...todo, order: index + 1 } 
      }
      return todo
    }))

  }

/* for example:
[{title: 'apple', order: 1}, {title: 'banana', order: 2}, {title: 'pear', order: 3}] => delete banana => [{title: 'apple', order: 1}, {title: 'pear', order: 2}] */

I wrote this solution based on the suggested options:

  const deleteTodo = (id) => {
    const newTodos = todos
      .filter(todo => todo.id !== id)
      .map((todo, index) => ({ ...todo, order: index + 1 }))
    setTodos(newTodos)
  }


Solution 1:[1]

  1. Filter to delete
  2. map to change the order value

const items = [{
  title: 'apple',
  order: 1
}, {
  title: 'banana',
  order: 2
}, {
  title: 'pear',
  order: 3
}]
//Delete {title: 'banana', order: 2}
const newItems = items.filter(el => el.title !== "banana").map(el => el.order > 2 ? ({ ...el,
  order: el.order - 1
}) : el)

console.log(newItems)

Solution 2:[2]

You have to filter the array that doesn't have the specific id and assign its order later

const deleteTodo = (id) => {
  const newTodos = todos.filter(todo => todo.id !== id)

  newTodos.map((todo, index) => {
    return {
      ...todo,
      order: index
    }
  })

  setTodos(newTodos)
}

Solution 3:[3]

This function will get the result you are looking for but not with removing. I recreate the array with the objects excluding the one you want to remove and give them the new ordering.

const data = [{title: 'apple', order: 1}, {title: 'banana', order: 2}, {title: 'pear', order: 3}];

function removeObjectAndReorder(data, orderToRemove){
  let result = [];
  let counter = 0;
  for (let i = 0; i < data.length; i++){
    if (i+1 !== orderToRemove){
      result.push({
        'title': data[i].title,
        'order': ++counter,
      })
    }
  }
  return result;
}

console.log(removeObjectAndReorder(data,2)); // Remove banana (order = 2)

Solution 4:[4]

const list = [
    {id: 1, title: 'apple', order: 1},
  {id: 2, title: 'banana', order: 2},
  {id: 3, title: 'pear', order: 3},
];

const deleteItem = (id) => {
    const newList = [...list]
    .sort((a,b) => a.order - b.order) // make sure list is in order
    .filter(el => el.id !== id) // filter out the selected item
    .map((el, i) => ({...el, order: i+1})); // Change the order values
  return newList;
}

console.log(deleteItem(2));

Solution 5:[5]

You can try this one

const deleteTodo = (id) => {

  const targetIndex = todos.findIndex((todo) => todo.id === id);

  if (targetIndex < 0) {
    // target element was not found. you need to handle this case
    return;
  }

  const updatedTodos = todos.reduce((accumulated, todo, index) => {
    if (index < targetIndex) {
      accumulated.push(todo);
    } else if (index > targetIndex) {
      accumulated.push({ ...todo, order: todo.order - 1 });
    }
    return accumulated;
  }, []);

  setTodos(updatedTodos);
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Cesare Polonara
Solution 2 Geeky Quentin
Solution 3 holydragon
Solution 4 bgcodes
Solution 5