React State - Avoiding Object Duplication
Tags: javascript, react, beginners, webdev
Published: 2023-03-05 08:26:19

When developing on the client side of Web, there are many situations where we need to implement scenarios like:

* When one item is selected in an array, the information related to that item must be displayed.

In this situation, let's look at how to avoid state duplication and errors.

### Code Examples
```jsx
const initialPeoples = [
  { name: "John", age: 20 },
  { name: "Jenny", age: 26 },
  { name: "Peter", age: 30 },
];

function AgeCounter() {
  const [peoples, setPeoples] = useState(initialPeoples);
  const [selectedPeople, setSelectedPeople] = useState(null);

  return (
    <>
      <ul>
        {peoples.map((people) => (
          <li
            key={people.name}
            onClick={() => {
              setSelectedPeople(people);
            }}
          >
            {people.name}, age {people.age}
          </li>
        ))}
      </ul>
      <button
        onClick={() => {
          setPeoples(
            peoples.map((people) => ({ ...people, age: people.age + 1 }))
          );
        }}
      >
        Happy New Year!
      </button>
      <div>
        selected people is: {selectedPeople?.name}, age {selectedPeople?.age}
      </div>
    </>
  );
}
```
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iy5gyy4kv7kmh8ka0bdq.png)

The code above will work as follows:

* Three objects that contain information about people exist in `initialPeoples`.
* Displays information of those people below the `<ul>` tag.
* When a specific person is clicked, the object corresponding to that person is saved in `selectedPeople`.
 * Displays the selected `selectedPeople` information at the bottom of the screen.
* When the `Happy New Year!` button is clicked, the age of the people increases by one.
 * The age displayed in selectedPeople is also increased by one.
At first glance, the code may seem fine, but there is an issue.

When John is selected and the `Happy New Year!` button is clicked, the age displayed in `selectedPeople` does not increase.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/epwbiwdeyhhpys19pu4m.png)

The reason for this is that the object saved in `selectedPeople` and the object I created by clicking the `Happy New Year!` button are different objects.

```jsx
<button
  onClick={() => {
    setPeoples(peoples.map((people) => ({ ...people, age: people.age + 1 })));
  }}
>
  Happy New Year!
</button>
```

`setState(setPeoples)` does not operate by modifying some properties of the previous object with a pointer to the previous object within the rendering lifecycle, but always forces the creation of a new object.

By using the object creation reservation keyword `{}` in `peoples.map((people) => ({ ...people, age: people.age + 1 }))`, a new object was saved in the new array created by `map`. Therefore, the age of the new object in the new array and the object in `selectedPeople` are not related at all, so clicking the `Happy New Year!` button does not increase the age.

This is also an anti-pattern that unnecessarily duplicates objects.

### How can we modify it?

Replace the state named `selectedPeople` with a state named `selectedPeopleName`, which holds the unique name of a person as its value. Then declare selectedPeople as a regular variable and use it as follows:

```jsx
const initialPeoples = [
  { name: "John", age: 20 },
  { name: "Jenny", age: 26 },
  { name: "Peter", age: 30 },
];

function AgeCounter() {
  const [peoples, setPeoples] = useState(initialPeoples);
  const [selectedPeopleName, setSelectedPeopleName] = useState(null);
  const selectedPeople = peoples.find(
    (people) => people.name === selectedPeopleName
  );

  return (
    <>
      <ul>
        {peoples.map((people) => (
          <li
            key={people.name}
            onClick={() => {
              setSelectedPeopleName(people.name);
            }}
          >
            {people.name}, age {people.age}
          </li>
        ))}
      </ul>
      <button
        onClick={() => {
          setPeoples(
            peoples.map((people) => ({ ...people, age: people.age + 1 }))
          );
        }}
      >
        Happy New Year!
      </button>
      <div>
        selected people is: {selectedPeople?.name}, age {selectedPeople?.age}
      </div>
    </>
  );
}
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ahf3teh25t9964ozw2o8.png)



Now, even if you select John and press the `Happy New Year!` button, the age will increase properly.