Understanding React States for Proper State Management.
Tags: react, webdev, javascript, beginners
Published: 2024-02-12 08:45:32

The most interesting thing any beginner gets to learn about React is the React state. Now the question is, what is the React state? Why do we call it a state? And most importantly, why do we need it in React applications? Not to forget about how we use it in React applications. In this article, we will learn about the React state, what it is, what it does, why we need it, and how to use it in React applications.

We want to make our work in this learning exercise as easy as possible. For that reason, we will break down this topic into the following sections:

1. Foundational understanding of React States.
2. The difference between States and Props.
2. Immutability in React states and why is it important to keep states immutable.

By covering the above subtopics, you will have more than what you need to start using React states in your components. Let us begin by looking at the foundations of the React state.


### 1. Foundational Understanding of React State.
Now if you are wondering about what React state is, this section will help you relax your mind about it. We will define what a state is with an example and discuss why React states are important.

Before thinking about states in the technical sense, consider a state as an English word. What comes into your mind when you hear the word state? The current condition of something? What is currently happening around you? Well, all those make sense as states in the real world. 

In React, the state is a feature that enables React to keep track of the nature of data being rendered in each component. State enables a component to remember what it is supposed to render on every render. React provides an inbuilt hook called the `usesState` hook that is used to handle states.

Take for example a simple component that takes input of product quantity from the user and displays it on the screen:

![Initial product quantity](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0knf0ehnmkt4kkf1mhvr.png)



The following code snippet describes the component that renders the elements shown in the screenshot above:

```
import { useState } from 'react'

const ProductQuantity = () => {
    const [quantity, setQuantity] = useState(0)

    return (
        <div>
            <input type="number" value={ quantity } onChange={
                (e) => setQuantity(Number(e.target.value))
            } />

            <h1> Current Quantity: { quantity }</h1>
        </div>
    )
}
```
The code snippet above does the following:

i). It initializes the state called `quantity` with the value  `0` using the `useState` hook 

ii). The useState hook returns an array containing the following two items:

- A variable that keeps the initial value of the state 
- A function that can be used to update the state. 

In this case, the state is stored in the variable named `quantity` and the function for updating the quantity is called is stored in a variable called `setQuantity`.

ii). The component renders a number input field with a default value of `0`. The text input field has a change event handler; an anonymous function that calls the updater function, `setQuantity` with the value of the input.

iv). Finally, the component renders the value of the `quantity` in a heading tag.

The value of the quantity can be changed to any number and it will be displayed instantly, for example, say you want to input a new quantity as `10000`. It would look something like this:

![Update quantity](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ns27w6o5c5cuqyqy75om.png)



Without the state variable and the state setter function, the component would not know that the value of `quantity` has changed and therefore it should rerender the new value. States tell a component what to render.



### 2. The difference between props and states.
If you are sequentially learning React, you must have used props to supply data to components. Now you might be thinking that props also tell components what to render, why do we need to learn about this new concept called states? The thing is, props tell a component about the changes that occur outside the component and states tell a component what happens to the data inside itself. 

Let us adjust our  `ProductQuantity` component to accept a prop. This time, let us supply a new value called `unitPrice` to the component using a prop. We want to use this value to calculate the price of the products when we update the quantity. The final rendered component with a `unitPrice` of `240` would look like the screenshot below:

![Quantity with unit price](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m3yru5iidnog9mjuoozd.png)



We can adjust our components to render the above information as follows:

```
import { useState } from 'react'

const ProductQuantity = ( { unitPrice }) => {
    const [quantity, setQuantity] = useState(0)

    return (
        <div>
            <input type="text" value={ quantity } onChange={
                (e) => setQuantity(Number(e.target.value))
            } />

            <h1> Current Quantity: { quantity }</h1>
            <h2>Unit Price: { unitPrice }</h2>
            <h3> Total Cost: {quantity * unitPrice }</h3>
        </div>
    )
}
```

The code snippet above does the following new things:

- The component accepts a unit price prop (`unitPrice`) of type number
- The component displays the unit price in a level 2 heading tag  (`h2`)
- Finally, the component calculates the total cost of the quantity of products entered and displays it in a level 3 heading tag `h3`.


As we said earlier, `props` are values supplied to a component by its parent component.  We can call our updated component in a parent component to supply the value of the `unitPrice` prop, as shown below:

```
    import ProductQuantity from './ProductQuantity'

    function App() {
        const unitPrice = 240
        
        return (
            <div>
                <ProductQuantity unitPrice={unitPrice} />
            </div>
                
        )
    }
```

From the above code snippets, we can see that props transfer information about changes that occur in the parent component (`App`) while a state takes care of the changes that occur in the current component (`ProductQuantity`). The prop (`unitPrice`) is initialized and maintained in the parent component while the state (`quantity`) is initialized and maintained by the current component.

Now with the above setup, we can update the quantity of products and the total will be displayed instantly. For example, say we change the quantity of products to 29, the updated total will be displayed as shown below.

![Updated total](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k9syigtni1fnnganqd7g.png)



### 3.) Immutability in React states and why is it important to keep states immutable.
What does it mean for something to be immutable? An immutable object is an object that cannot be changed. React states are technically mutable but it is recommended to treat them as if they are immutable. This means you should not modify a state during an update but you should replace it. 

For example, we can create a new component called `PurchasedProduct` that takes, `name`, `quantity`, and `unitPrice` input from the user. The product renders the values of the product properties including gross total on the screen as shown below.

![Inititial purchased product](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lhiuyxpkvk90ddrsnh9i.png)



The code snippet below renders the elements shown in the screenshot above:
```

import { useState } from 'react'

const PurchasedProduct = () => {
    const [product, setProduct] = useState({
        name: '',
        quantity: 0,
        unitPrice: 0
    })
    return (
        <div>
            <div>
                Name: <input type="text" />
                Quantity: <input type="number" />
                Unit price: <input type="number" />
            </div>
            <h1>Name: {product.name}</h1>
            <h1>Quantity: { product.quantity}</h1>
            <h1>Unit price: {product.unitPrice }</h1>
        </div>
    )
}
```

Notice that we have not handled any change events in the input fields. To learn the importance of keeping states immutable, we will break down this section into the following:

- a) Problems associated with mutating states
- b) How to maintain immutability while updating states
- c) Using the spread operator to update states

#### a) Problems associated with mutating states.
One way to update the state of the product with the changes in input values would be to update every single property that is related to each input field. The code snippet is shown below.

```
import { useState } from 'react'

const PurchasedProduct = () => {
    const [product, setProduct] = useState({
        name: '',
        quantity: 0,
        unitPrice: 0
    }) 

    const updateName = (e) => { product.name = e.target.value }

    const updateQuantity = (e) =>{ product.quantity = Number(e.target.value) }

    const updateUnitPrice = (e) =>{ product.unitPrice = Number(e.target.value) }

    return (
        <div>
            <div>
                Name: <input type="text" onChange={updateName}/>
                Quantity: <input type="number" onChange={updateQuantity}/>
                Unit price: <input type="number" onChange={updateUnitPrice}/>
            </div>
            <h1>Name: {product.name}</h1>
            <h1>Quantity: { product.quantity}</h1>
            <h1>Unit price: {product.unitPrice }</h1>
        </div>
    )
}
```

Surprisingly, the code snippet above seems to be so simple and straight forward but it does not update any states. Nothing changes in the display at all when you try to change the values in the input field. The screenshot below shows all the input fields populated with input data but nothing new is rendered.

![Mutated state](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mn8o6nj1bcmkl0bl5mau.png)




This is what happens when you try to change state directly like you would change the value of any variable. The state does not get updated at all and therefore no rerendering occurs.


Let us try doing it differently, this time we will use, the `setProduct` function to update the state.

```
const PurchasedProduct = () => {
    const [product, setProduct] = useState({
        name: '',
        quantity: 0,
        unitPrice: 0
    }) 

    const updateName = (e) => { setProduct({ name: e.target.value }) }

    const updateQuantity = (e) =>{ setProduct({ quantity:Number(e.target.value)} ) }

    const updateUnitPrice = (e) =>{ setProduct({ unitPrice: Number(e.target.value) }) }

    return (
        <div>
            <div>
                Name: <input type="text" onChange={updateName}/>
                Quantity: <input type="number" onChange={updateQuantity}/>
                Unit price: <input type="number" onChange={updateUnitPrice}/>
            </div>
            <h1>Name: {product.name}</h1>
            <h1>Quantity: { product.quantity}</h1>
            <h1>Unit price: {product.unitPrice }</h1>
        </div>
    )
}
```

Let's render our component with the above changes and see what happens. This time, we get something better. 

The first value, `name`, updates as expected as shown below:

![Updated name field](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/shjkzqvxqtxxnpu3byle.png)




Let us try the second value, product `quantity`:

![Updated quantity field](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mixqsdgg1z4e3x0a01ct.png)



Now we have a problem here, the second value updates well but the first one disappears.

Let's see what happens with the last value, `unitPrice`:


![Updated Unit price](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4za4h5mt15q4z94ryh94.png)



Similarly, the unit price gets updated and rendered as expected but the rest of the values are not rerender as we expected. 


What is happening here? According to our code, we are updating a single property of the `product`  object at every input field. This means that we are trying to modify the `product` partially at every step. 

The problem with this approach is that every time we update just one value, the initial object is replaced with a new object with just one property. When we update the `name`, we end up with a new object, `{name: <new name>}`. The new object does not know anything about `unitPrice` or `quantity`. Updating the next value, `unitPrice` does the same thing, it replaces the current object with a new object that has no `name` or `quantity` properties. Therefore, when the component is being rerendered, only one value gets rendered at a time, the most recent update.


#### b) How to maintain immutability when updating states.
The correct way to update the state in the `PurchasedProduct`  component is to replace the whole `product` object with a new object containing all its properties. In other words, copy the object and only change the value you are interested in changing without losing the other values. The code snippet is shown below:

```
const PurchasedProduct = () => {
//The code that initializes the state goes here

    const updateName = (e) => { 
        setProduct(
            { 
                name: e.target.value,
                quantity: product.quantity,
                unitPrice: product.unitPrice 
            }
        ) 
    }

    const updateQuantity = (e) =>{ 
        setProduct(
            { 
                name: product.name,
                quantity:Number(e.target.value),
                unitPrice: product.unitPrice
            } 
        ) 
    }

    const updateUnitPrice = (e) =>{ 
        setProduct(
            { 
                name: product.name,
                quantity: product.quantity,
                unitPrice: Number(e.target.value) 
            }
        ) 
    }

    return (
        //JSX goes here
    )
}
```



With the changes described in the above code snippet, we can now get a component that behaves just as we expect. In the screenshot below, all the input fields are filled and all the values are displayed as expected.

![All inputs rerenderd](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2t8yhlek7t9j1b5qgwgi.png)




This shows that states are managed better when they are treated as immutable. Every time you are updating a state, make sure you are replacing the whole state variable and not just modifying its parts. This approach applies to array variables too. When working with arrays in states, consider replacing the whole array when adding or removing an item from the array.

#### c) Using the spread operator.
A Less wordy approach to achieve the same goal above is to use the spread operator. The spread operator can save you a few lines of code and errors that you may introduce while copying the object. Below is a code snippet showing how the spread operator can make your life easier.

```
const PurchasedProduct = () => {
//State initialization goes here

    const updateName = (e) => { 
        setProduct(
            { 
                ...product,
                name: e.target.value
            }
        ) 
    }

    const updateQuantity = (e) =>{ 
        setProduct(
            { 
                ...product,
                quantity:Number(e.target.value),
            } 
        ) 
    }

    const updateUnitPrice = (e) =>{ 
        setProduct(
            { 
                ...product,
                unitPrice: Number(e.target.value) 
            }
        ) 
    }

    return (
       // JSX goes here
    )
}
```
The spread operator enables you to override one property of the `product` object and leave the rest as they are.



## Conclusion
In conclusion, understanding the React state as the memory of a component is crucial to the success of your user interface projects. In this article, we have learned the following concepts about React state:
- How to initialize state using the useState hook
- How to update state using the `set` state function
- The difference between states and props
- Problems associated with mutating states
- How to keep states immutable and why it is important to keep them immutable.
- How to update states using the spread operator.

Visit [the react documentation](https://react.dev/learn/render-and-commit) to learn more about how state triggers rerendering in React applications.