React hooks update array of object I have declared a react hook which will contain an array of object as follows:
const [rowDataTracker, setRowDataTracker] = useState([]);

Now I need to update the hook to basically create a payload as the following:
[
  {id: 100, payload: {field1: &quot;value&quot;, field2: &quot;value&quot;}}, 
  {id: 105, payload: {field1: &quot;value&quot;, field3: &quot;value&quot;}},
  {id: 109, payload: {field4: &quot;value&quot;}}
]

I need to check the following condition Before updating the hook:

Need to first check if the id exists in the array or not
if the id exists, then need to update/add the filed to the payload object
if the id does not exist, add a new object to the array with id and the field



const ifItemExist = (arr, item) =&gt; {
  return arr.findIndex((e) =&gt; e.id === item);
};
function storeEdit(rowId, field, newValue) {
  let itemIndex = ifItemExist(rowDataTracker, rowId);
  let newArr = [...rowDataTracker];
  if (itemIndex &gt; -1) {
    newArr[itemIndex]["payload"][columnId] = newValue;
  } else {
    const obj = {
      itemNbr: rowId,
      payload: {
        [field]: newValue
      }
    };
    newArr.push(obj);
  }
  setRowDataTracker(newArr);
}



I am not sure if this is the correct way to update a hook.
Any review and suggestion will be appreciated.
Mutation You are mutating the existing state when you do
let newArr = [...rowDataTracker];
// ..
  newArr[itemIndex][&quot;payload&quot;][columnId] = newValue;

because spread syntax only creates a shallow copy of the array or object. This should never be done in React. (See end of answer for how to fix it - create the new obj no matter what, then either push it to the new array, or replace the existing object in the array, without mutating the existing object in the array)
Dot notation Most people prefer to read and write using dot notation in JS when possible - it's more concise and easier to read. ESLint rule: dot-notation. You can use .payload instead of [&quot;payload&quot;].
Property/variable naming The rowId refers to the same thing as the itemNbr, which looks to refer to the same thing as the id in the rowDataTracker array. It's good to be consistent with variable names and properties when possible - consider picking one and sticking with it. If you use the variable name itemNbr, you can use it  shorthand in the object literal:
const obj = {
  itemNbr,
  // ...

id or itemNbr or both? You check against the id property in rowDataTracker in ifItemExist, but you push to the same array with a property named itemNbr. This looks very likely to be  a typo. You probably meant to push an object with an id property, or you wanted to check against the itemNbr property instead.
Misleading function name ifItemExist doesn't return a boolean indicating if an item exists - it returns the index of the possibly-existing item. Maybe call it getItemIndex.
Prefer const over let when the variable name doesn't need to be reassigned.
In all:
const getItemIndex = (arr, item) =&gt; {
  return arr.findIndex((e) =&gt; e.id === item);
};

function storeEdit(id, field, newValue) {
  const itemIndex = getItemIndex(rowDataTracker, id);
  const obj = {
    id,
    payload: {
      ...rowDataTracker[itemIndex]?.payload,
      [field]: newValue
    }
  };
  if (itemIndex === -1) {
    setRowDataTracker([...rowDataTracker, obj]);
    return;
  }
  const newArr = [...rowDataTracker];
  newArr[itemIndex] = obj;
  setRowDataTracker(newArr);
}