Home > Mobile >  How to update React State in an array of objects? Update if id exists, otherwise append
How to update React State in an array of objects? Update if id exists, otherwise append

Time:10-17

the parent component gets the object from the child component through callback function. I want to check if the object with the specfic rowID exists, if it exists then it should update the object with the passed value "val", otherwise it should append the object inside the state array. My answer is appending correctly but I am unable the update the values, please help me out. the object which is being passed is attached at the end.

const [state, setState] = React.useState([]);

const existingProduct = state && state.find((product) => product.rowID == index);
if (!!existingProduct === false) {
  return setState((prevState) => [...prevState, object]);
}
console.log(state);

let payload = {
          quantity: quantityRef.current && 
          quantityRef.current.value,
          name: product && product.NAME,
          unit: product && product.UNIT,
          PRICE: product && product.PRICE,
          oldQuantity: oldQuantity,
          rowID: id,
        };

EDIT: SOLVED

  const getData = async (index, val, object) => {
const existingProduct = state && state.find((product) => product.rowID == index);
if (!!existingProduct === false) {
  return setState((prevState) => [...prevState, object]);
}
setState(
  state.map((product) => (product.rowID === index ? { ...product, quantity: val } : product))
);

};

CodePudding user response:

Before answering I have to mention !!existingProduct === false is very confusing to read. You can simply do !existingProduct to achieve the same result.

Your code is missing some parts so I'm gonna have to infer, but I assume the index value does what you want, and you're already detecting if the product is present or not in the array. And you're appending the new product in the if, so what we need is an else.

What I would do is copying the state into a new array, replacing the value in the new array, and setting this new array as the new state. To know which position of the array you need to update you can use the findIndex() method instead of find(). So instead of existingProduct being an object, it's the index of the array that contains that object (so I would call it existingProductIdx just to make it clear):

if (existingProductIdx === -1) { // product doesn't exist in the array
  ...
} else { // product exists
  const newSate = [...state] // creates a copy of the current array
  newState[existingProductIdx] = payload // set the position of the array to payload (or whatever should be the new value)
  return setState(newState)
}

A few notes:

  • I assume you're doing this inside a function that you want to return earlier and that's why you have that return statement. Otherwise you don't need it
  • I don't remember right now but I'm pretty sure setState has no return value, so instead you can do setState(newState); return;. Or, you may not need to return at all.
  • I would suggest you change the state and setState variable names to something more meaningful, like products and setProducts
  • Again, I hope that middle section of your code sample belongs into a function, otherwise that would mess up your component (which should return a render function)
  • Related