const handleAddNewItemSubmit = (title, id) => {
const listIndex = lists.findIndex((list) => list.id === id);
const newData = [...lists];
newData[listIndex].items = [...newData[listIndex].items, { title }];
setLists(newData);
};
In the above code, when you do const newData = [...lists] it just do shallow copy, i.e., only the top level references will be different but if there are any nested objects, they'll have same references as of lists.
So when yo do newData[listIndex].items you are actually referring to the same object i.e., lists[listIndex].items. Since newData[listIndex].items is an array which in turn is an object it'll have the same reference as of lists[listIndex].items.
So, ultimately you end up mutating the state. In order to avoid that, we can do the state update in different ways
const handleAddNewItemSubmit = (title, id) => {
setLists(oldLists => oldLists.map(list =>
list.id === id ? ({
...list,
items: [...list.items, { title }]
}) : list))
}
Below I have simulated two examples one which mutates top level object, another which mutates nested objects after spreading.
let lists = [
{
id: 'd8t4gf',
title: 'Working on',
items: [{ title: 'Item 1' }, { title: 'Item 2' }, { title: 'Item 3' }],
},
{
id: '8jy8g',
title: 'Done',
items: [{ title: 'Item 1' }, { title: 'Item 2' }],
},
];
const addNewTitleOnTopLevel = (title) => {
const newData = [...lists];
newData.push({id: '123', title});
//Since doing `[...lists]` will do a shallow copy, the lengths will be different;
console.log(newData.length, lists.length);
//The objects are different so, it'll be false.
console.log(newData === lists);
}
const addNewTitleInnerItems = (title, id) => {
const listIndex = lists.findIndex((list) => list.id === id);
const newData = [...lists];
newData[listIndex].items = [newData[listIndex].items, {title}]
//Since `newData[listIndex].items` & `lists[listIndex].items`
//are pointing to same references, their length will be same
console.log(newData[listIndex].items.length, lists[listIndex].items.length);
//To know if they both are same or not
console.log(newData[listIndex].items === lists[listIndex].items);
}
addNewTitleOnTopLevel("test");
addNewTitleInnerItems("test", '8jy8g');