Mourad Hegazy
Mourad Hegazy

Reputation: 47

How to update react JS state functional component

How can I change a specific object in a state for example, I have data like this

const colors= [
      {
        id: 1,
        name: "red",
      },
      {
        id: 1,
        name: "green",
      },
      {
        id: 2,
        name: "blue",
      },
    ];

const storage = [{
id:2,
name:"64 GB"
},
{
id:2,
name:"128 GB"
]

The state value should be like this [{id:1, name:'red"}, {id:2,name:"128GB"}]

Is there any way to update the state based on the id only? For example: I need to loop on the data and if the state.id === id it will update that specific object. So in our example, I need to update the state to be [{id:1, name:'green"}, {id:2,name:"128GB"}] if the state.id === 1

Thanks in advance

Upvotes: 0

Views: 404

Answers (2)

Majid M.
Majid M.

Reputation: 4954

You can update your array state of objects with a shallow copy and change the value, same as bellow:

import * as React from "react";

export default function App() {
  const [colors, setColors] = React.useState([
    {
      id: 1,
      name: "red"
    },
    {
      id: 1,
      name: "green"
    },
    {
      id: 2,
      name: "blue"
    }
  ]);
  const updateState = (id, name) => {
    let copy = [...colors];
    let color = copy.filter((x) => x.id == id)[0];
    if (!color) return;
    let index = copy.indexOf(color);
    color.name = name;
    copy[index] = color;
    setColors(copy);
  };
  return (
    <div className="App">
      {colors.map((color, index) => (
        <>
          <p>
            {color.id} : {color.name}
          </p>
        </>
      ))}
      <button
        onClick={() => {
          updateState(2, "yellow");
        }}
      >
        update
      </button>
    </div>
  );
}

Edit mutable-wildflower-n10ys

Upvotes: 1

Giovanni Esposito
Giovanni Esposito

Reputation: 11156

You could always copy the current value in local var, modify and set again the state. Something like:

const [colors, setColor] = useState([
  {
    id: 1,
    name: "red",
  },
  {
    id: 1,
    name: "green",
  },
  {
    id: 2,
    name: "blue",
  },
]);

...

let colorCopy = Object.assign({}, colors); //<-- make a copy of color
colorCopy = colorCopy.map(x => { 
   if (x.id === 1) x.name = "black";
   return x;
}; // modify name property for id === 1
setColor(colorCopy); //<-- set new state

EDIT

@Nicolas Menettrier and @andy mccullough raised a good point of discussion: "Why call Object.assign if map function already does a copy of colors array?" This is correct so you could also write above code in this way:

let colorCopy = colors.map(x => { 
   if (x.id === 1) x.name = "black";
   return x;
}; // modify name property for id === 1
setColor(colorCopy); //<-- set new state

1 line code less.

Upvotes: 2

Related Questions