I have a problem with updating my object in array.
const [list, setList] = useState([]);
const changeRecordIndex = list.findIndex((recordItem) => recordItem.id === recordID);
I creat new array, copy object wich i need and then change one parametr of object. It’s look like great! But in this case i have a problem with final array – i have 2 similar objects with differen paramet wich i’m tring to change.
setList([...list, { ...list[changeRecordIndex], taskText: liItem.innerText }]);
In this case everything is ok
const newArr = [...list];
newArr[changeRecordIndex] = { ...newArr[changeRecordIndex], taskText: liItem.innerText };
setList(newArr);
What’s wrong with first case?
3
Answers
The problem with your first approach is that you’re adding the updated object to the array without removing the old one, so you end up with two objects: the original and the updated one.
In your first case:
This adds all existing items from list, including the one you’re trying to update, and then adds the updated object to the end. This creates a duplicate.
Correct approach (second case):
In this approach, you’re replacing the object in the array without duplicating it. Stick with the second method to avoid duplicates!
Use Array.map() to iterate the state, and when you encounter the item you want to update, return a new item. For the rest just return the existing item.
Array.map()
also returns a new array, so you’re shallow cloning the array, and the changed item at once.In addition, when you want to update the previous state instead of replacing it, pass an updater function when you’re setting the state. The updater function is called with the previous state.
A newer option is to use Array.toSpliced(), which can remove/add items at a specific index:
As Andy said above, the issue with your code is that you’re not removing the old object from the array.
Another alternative (more concise, in my opinion) would be to use the Array’s toSpliced() method, like so:
P.S.: make sure to guard against findIndex()‘s possible negative result (-1)