reactjsreact-state

Set new state in object in array


I have a problem with updating my object in array.

const [list, setList] = useState([]);

const changeRecordIndex = list.findIndex(
  (recordItem) => recordItem.id === recordID
);

I create a new array, copy the object which I need and then change one parameter of the object. It looks like great! But in this case I have a problem with final array - I have 2 similar objects with different parameters which I'm trying 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?


Solution

  • 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.

    setList(prevList => prevList.map(recordItem => 
      recordItem.id === recordID
      ? { ...recordItem, taskText: liItem.innerText }
      : recordItem
    ));
    

    A newer option is to use Array.toSpliced(), which can remove/add items at a specific index:

    setList(prevList => {
      const changeRecordIndex = list.findIndex(
        recordItem => recordItem.id === recordID
      );
      
      return prevList.toSpliced(changeRecordIndex, 1, {
        ...prevList[changeRecordIndex], 
        taskText: liItem.innerText 
      });
    });