How to Easily update an Object that's in state in React
Tags: react, state, beginners, webdev
Published: 2023-01-17 03:12:29

**Contents**

- [Introduction](#introduction)
- [Updating object that's in state ](#section-1)
- [Creating an Up vote function ](#section-2)
- [Implementing The Update Votes Button](#section-3)
- [Showcasing mutation](#section-4)
- [One Command for Updating Object in state](#section-5)
- [Simple Way To Copy JavaScript object For easy Property update](#section-6)
- [Conclusion](#conclusion)

---

##Introduction <a name="introduction"></a>
One of the fundamental concepts of the React framework is **state management.** State in react can hold any kind of JavaScript data types ranging from the primitive data types like  *string, number and boolean* to the complex data types like *objects*. 

There are many ways to introduce state into your component, one of the many ways is using the hook: `useState`. Typically, the useState hook allows us to initialize the state variable.

```react
const newStudent = {
name:'Jane Doe',
age: 15
}
const [student, setStudent] = useState(newStudent);
```
On the other hand, an **Object** in JavaScript is a real world entity  that contains properties and or type. An example of an object can be as put in the above code; a student with properties *name*, *age*.

Further we can also have an array of objects which is fairly common in many applications

```react
//an array of song objects with properties like title and votes
const songList = [
  {
    id: 0,
    title: "All for you",
    votes: Math.floor(Math.random() * 5 + 1),
  },
  {
    id: 1,
    title: "Always win",
    votes: Math.floor(Math.random() * 5 + 1),
  },
  {
    id: 2,
    title: "Grateful",
    votes: Math.floor(Math.random() * 6 + 2),
  },
];
```
The song list array is comprised of objects and each object is made up of 3 properties namely; id, title and votes.

We are using `Math.Random()` function to prepopulate the `votes` property that is in our song object, this will help us to have initial votes on the first render. You can read more about Math.random() [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random) 

##Updating object that's in state <a name="section-1"></a>
Just as any other state in react, an object that's in state is also subject to change, however there are precautions or standards that must be met when updating an object that's in state. In this article I'll help you to update an object in state in a more clean way.

For example for us to make the above songList array of objects editable or updatable we need to put it in state inside a component.

```react
  const [songs, setSongs] = useState(songList);
```

 if we can provide a user interface for the array of objects above and traverse the `songList` array that is above so that a user should be able to vote for a song that he wishes it may look like this.


```react 
return (
      <ul className="song-list">
        //the map array function will help us to traverse through the songs array
        {songs.map((song) => (
          <li key={song.id} className="song-item">
            <p className=""><span className="votes">{song.votes}</span> votes</p>
            <div className="title">{song.title}</div>
            <div className="caret">
              <BiCaretUp size={24} />
              <span className="text">Vote</span>
            </div>
          </li>
        ))}
      </ul>
  );};
```
and suppose after styling the output looks like this.



![A Simple UI that allows a user to vote for countless times for a song  he likes](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fzdvr38p1e0pom2ldf2j.PNG)

This simple UI will allow any user to click on the preferred song and vote for it countless times ( *not applicable in real world applications* ).

### Creating an Up vote function <a name="section-2"></a>

For us to update the vote after user clicks on the vote button (caret) we need to define a function that will do this work for us. So lets define a function `onVote()` that will be called whenever a user clicks the vote caret.

The function will receive a song ID for the clicked song and will 

```react
const onVote=(id)=>{
   //code for updating the votes the chosen song
}
```

and then we will add an `onClick()` attribute on our button in our UI to capture any clicks on our vote button

```react
...
// adding the onClick function 
<div 
  onClick={()=>onVote(id)} 
  className="caret">
     <BiCaretUp size={24} />
     <span className="text">Vote</span>
 </div>
....
```
Whenever a user clicks on this div an the song ID will be passed to this `onVote()`.

## **Implementing The Update Votes Button** <a name="section-3"></a>
There are many ways how we can update the votes after user clicks the vote button. But one thing we have to do is avoid something called **mutation**.

>The major concept to grab when updating object in state is that: **An object once created, it never changes** , and its variable should never be reassigned. The term mutation refers to 
 the situation that a value is changed in-place updating a value stored somewhere in memory.  In React, **state is considered to be an immutable object**, meaning that you should **not** directly change the state object. 

## Showcasing Mutation <a name="section-4"></a>

For example, to implement the `onVote()` function one can do this just to update the votes in a single specified object.

```react
const onVote = (id) => {
    songs.map((song) => {
      if (song.id === id) {
      //incrementing the votes of the specified song after user clicks
         song.votes = song.votes+1
        }
    });
  };
```
The situation above portrays  the concept of mutation. We are directly accessing the `song.votes` and incrementing or in other words changing it directly and while its in memory.  Respectively this will not work or it may either bring an error. However, there is a specific way to do this without complications.

##One Command for Updating Object in state <a name="section-5"></a>
There is only one rule that works and never fails whenever you want to update object in state.

> **Thou shall copy first and then modify**<a name=""></a>

What this means is that, to avoid mutation You have to create a new Object that will take the contents of the object that wants to be modified and modify the field that you want. In other words whenever you want to update an object in state *copy* the contents of the object on a new one and then update the object and the update state.

This may look something like this:

```react
const onVote = (id) => {
    const newSongs = songs.map((song) => {
      if (song.id === id) {
         const nextSong = {
            id:song.id,
            title:song.title ,
            votes:song.votes+1
        }
        return nextSong
      } else {
        return song;
      }
    });
    setSongs(newSongs);
  };

```

First, we use `map()` to traverse the songs array. Importantly, `map()` returns a new array as opposed to modifying the array `song`.

Next, as we traverse we check if the current song ID matches songID. If it does, we create a new object, copying over the properties from the original product object. We then overwrite the votes property on our new product object. We set it to the incremented vote count. So easy.


![a UI showing how the voting update is occuring](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fbq4ecii0rty2jeoiz6y.gif)

Her we can see using the above GIF that the votes are incrementing easily after we. REMEMBER! we are only modifying the votes property in our state. You can update many fields depending on the type of application you are developing.

---

##Simple Way To Copy JavaScript object For easy Property update<a name="section-6"></a>
As we have seen in the recent section that you first of all have to copy the object into   whole new object,


```react

   const newSongs = songs.map((song) => {
      if (song.id === id) {
         const nextSong = {
         //copying the song object values unto a new object 
            id:song.id,
            title:song.title,
            votes:song.votes+1
        }
```
hoever this can become so tiresome if the object can be so big that is when it has so any properties with it. suppose the object looks like this:

```react

const song ={
    id: 0,
    title: "All for you",
    votes: Math.floor(Math.random() * 5 + 1),
    duration: "5 min",
    type: "mp3",
    size: '5MB',
    available_online:true,
    artist:{
        name:'Jones Boy',
        adress:"300 longstreet ",
    }
  },

``` 
As you can see it has so many properties, and to copy them just as we did above by doing something like `title = song.title` can be so tiresome.

Here is where the `Object.assign()` function comes in.

This function is used places where we want to create a
modified version of an existing object.



````react
  const onVote = (id) => {
    const newSongs = songs.map((song) => {
      if (song.id === id) {
        return Object.assign({}, song, {
          votes: song.votes + 1,
        });
      } else {
        return song;
      }
    });
    setSongs(newSongs);
  };
````

We are passing three arguments to the function. The first argument is a new JavaScript object, the one that `Object.assign()` will basically return. The second is the object whose properties we’d like to build off of. The last is the changes we’d like to apply.


So there is no need to assign all those properties one by one to the new object.

##Conclusion <a name="conclusion"></a>
This article has clearly explained how to modify and update an object that's in state without mutation. It has also elaborated on the JavaScript function (`Object.assign()`) that easily copies an existing JavaScript object into a new one and returns a  modified object.