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.
Let's get building 🏗️
Consider the code for a simple counter functionality -
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.
Let's have a look at a common mistake developers tend to make when trying to update the state using the previous state :
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.
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).
Diving deeper into useState()
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.
Here are two frequently frequently asked questions when using useState():
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.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 whereuseState()
was called and prevents any default state overwrites during subsequent component renders.
Another important concept to understand is how to work with objects and useState():
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 -
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.
Top comments (0)