React useState() 🪝
Tags: webdev, javascript, react, codenewbie
Published: 2023-01-27 04:47:10

Let us first understand _state_ in React.

State can be imagined as the data or property that is used within an application. These data/property values would likely change over time and the State hook in React helps us track & manage the changing states.

To use the State hook, we need to import it as shown below:

`import React, {useState} from 'react'`

We can then invoke useState() inside the component function and pass an initial state(this value can be any type such as string, number or object) as an argument:

`const [count, setCountValue] = useState(0);`

The useState() hook returns an array, where the first element corresponds to the current state and the second element is a function that allows us to update the current state.
<br>

Let's get building 🏗️

Consider the code for a simple counter functionality -

```javascript
import React, {useState} from 'react'

const App = () => {
    
    const [count, setCountValue] = useState(1)

    const decrement = () => {
        setCountValue(prevState => {
            prevState-1
        })
    }

    const increment = () => {
        setCountValue(prevState => {
            prevState+1
        })
    }

    return(
        <div>
            <button onClick={decrement}> - </button>
            <span> {count} </span>
            <button onClick={increment}> + </button>
        </div>
    )
}

export default App;
```

Simplifying the code above...

`useState()` is called within the component function and an initial state(1) is passed to it. This means that when the component is rendered for the first time(when the page is loaded initially), the counter is set to 1.

As mentioned earlier, `useState()` returns an array with two elements. Here, using array destructing, the current state is stored in the `count` variable and the function to update the current state is `setCountValue`.

The `+` button triggers the increment function and `-` triggers the decrement function. I am using the setCountValue function to update the current state value.
<br>

Let's have a look at a _common_ mistake developers tend to make when trying to update the state using the previous state :

```javascript
const decrement = () => {
        setCountValue(count - 1)
    }
```

Why is the above approach an incorrect one to update the state value?
When we modify the state using the previous state value(in the above code we are using the count variable directly), we must use the function version of setting state as shown below.

```javascript
const decrement = () => {
        setCountValue(prevState => {
            prevState-1
        })
    }
```

`prevState` is the previous state snapshot that React provides. The reason behind using this approach is that the state updating function in React **schedules** the state update. By using the function version to set the state, we can ensure that the previous state is always updated(latest).
<br>
---

### <u>Diving deeper into useState()</u>

<img src="https://media.giphy.com/media/46zr6Ka7bUtFoc0uHZ/giphy.gif" />

Each time the state updating function is called, the state is updated and the component function from which the `useState()` is initialized is executed again.

It is also important to remember that `useState()` registers a different state for each component instance and React manages states independently on a per-component basis.
<br>

Here are two frequently frequently asked questions when using useState():

1. Why does useState() use `const` since the state value is updated? 
--> The way to think about this question is that each time the component is rendered(state update function is called), a new variable is created and managed somewhere else, internally, by React.

2. Does the default state not override the current state value each time the state updating function is called and the component is rendered?
--> React keeps track of the first instance where `useState()` was called and prevents any default state overwrites during subsequent component renders.
<br>

Another important concept to understand is how to work with objects and useState():

```javascript
    const [state, setState] = useState({count:4, toggle:'Yes'})
    const count = state.count
    const toggle = state.toggle

    function decrement() {
        setState((prevState) => {
            return ({
                count: prevState.count-1
            })
        })
    }
```

The above code is incorrect since the setState update function overrides the previous state with only the updated count(toggle:'Yes' is removed). 

The correct way to use an object is to _spread_ the previous state and then set the new state - 

```javascript
    function decrement() {
        setState((prevState) => {
            return ({
                ...prevState,
                count: prevState.count-1
            })
        })
    }
```

Finally, lets talk about an advance concept when using useState(). 

Consider setting the initial state as `a`: `useState('a')`. When using state hook, the initial state `a` is called each time the function is run. If a computationally complex argument is defined as the initial state, it would run during every subsequent component function render, leading to a degradation in performance. 

Therefore, there is another way to pass state to `useState()`, a function version.
`useState(() => {return 4})`

The approach runs the initial state function only during the first component render. This approach is preferred when we have a computationally intensive initial state.

---

The gamut of information around useState() can be overwhelming 🤯. Remember to go slow and understand the concepts as it would you build a 💪 base in React.
<br>