Understanding how the React state updates work is essential to work with state variables correctly. This article explains the correct ways to increment and append to React state variables.
No matter what task you perform on state variables, do not directly mutate the state variable. Always use the React-provided setter method to update the state. Let's take a look at a few examples.
Take a look at the below example. If you run this code, you will find that the counter updates every other click.
import { useEffect, useState } from "react"
export const StateUpdateExamples = () =>{
let [counter, setCounter] = useState<number>(0)
const updateCounter = () => {
setCounter(counter++) // WRONG
}
return(
<>
<div>{counter}</div>
<div><button onClick={updateCounter}>Update</button></div>
</>
)
}
I am doing two things wrong here.
Here is what happens in the first button click.
const updateCounter = () => {
//counter = 0
setCounter(counter++) // setCounter(0)
//counter = 1
}
My
const updateCounter = () => {
//counter = 1
setCounter(counter++) // setCounter(1)
//counter = 2
}
This time, I get a state update because my state changes from 0 to 1. This pattern follows for every consecutive button click.
In the above example, I updated the state with
const updateCounter = () => {
setCounter(counter+1)
}
My favorite is to use the previous state. That guarantees that I always get the up-to-date state variable value.
const updateCounter = () => {
setCounter((prevCounter) => prevCounter+1)
}
Take a look at the below code. I call the
import { useEffect, useState } from "react"
export const StateUpdateExamples = () =>{
let [text, setText] = useState<string>("")
const updateText = () => {
setText(text + "These ")
setText(text + "updates ")
setText(text + "are ")
setText(text + "batched ")
}
return(
<>
<div>{text}</div>
<div><button onClick={updateText}>Update</button></div>
</>
)
}
Under the hood, React batch those four state updates. When React executes them, first, React looks for the value of the text variable within the
There are many ways to update the state. If I build a string based on conditions, I will use a separate variable to build the string and update the state with the final string value.
const updateCounter = () => {
let dynamicString = ""
//Use any conditions to build the dynamicString
dynamicString += "These "
dynamicString += "updates "
dynamicString += "are "
dynamicString += "batched"
setText(dynamicString)
}
If I want to keep appending the values to the state variable, I will use the previous state variable value to append the new value.
const updateCounter = () => {
let dynamicString = ""
//Use any conditions to build the dynamicString
dynamicString += "These "
dynamicString += "updates "
dynamicString += "are "
dynamicString += "batched"
setText(prevText => prevText + dynamicString)
}
For some reason, If I want to update the state directly, I will use the previous state on each update statement. The previous value of the