The setState Callback in React
At first glance, React components’ .setState()
method seems simple enough. It updates the existing state to reflect the changes in the argument. However, many people don’t know that the .setState()
method also accepts another optional argument. This argument is a callback function, which is executed right after the state is updated.
In order to write more reliable code, you need to understand what the .setState()
callback function does and how you can use it.
Why Is the Callback Argument Necessary?
Most React developers don’t know that .setState()
method is asynchronous. The update doesn’t happen immediately. If you try to read the updated contents of state
right after a setState()
call, you might be unsuccessful or read the wrong data.
To resolve this problem, the setState()
method takes another optional argument - a callback function. The actions specified in the callback function will be performed only after the state is updated.
When to Use setState()
Callback?
As we mentioned above, the setState
call is asynchronous. It doesn’t update the state object immediately. If you want to perform a check or some other action based on the most recent update, using the setState()
callback is a good practice. However, it’s not the only way to perform such operations. We discuss the alternatives in later sections.
The setState()
callback is useful for these types of actions: making calls to the API, checking the content of state
to conditionally throw an error, and other operations that need to be performed right after the state
is updated. setState()
callback is also frequently used for validation.
For instance, if we want to use the <input>
to update the state, we can use the callback function to read the updated value with absolute certainty. Without a callback, we could be checking the stale, older versions of the state.
Code example:
class App extends Component {
constructor(props){
super(props)
this.state = {
text: ""
}
}
render() {
return (
<div>
<h1>Hello World</h1>
<input type="text"
onChange={(e) => this.setState({text: e.target.value},
() => console.log(this.state.text))}></input>
</div>
)
}
}
Callback Function vs render()
Skeptics might ask why I need setState()
callback when I can access the updated state
in the body of the render()
method?
The difference is, render()
method will run every time the state
is updated, whereas a setState()
callback will only run after updating the specific value in the state
.
.setState()
in an async
Function
Sometimes .setState()
method can be called in asynchronous functions. In this case, the state will not be updated immediately.
If you read the value of the state property using the this
keyword, you’re going to get an old value. On the other hand, the callback function is called once the async
task is done.
Alternative
React documents recommend that developers use the componentDidUpdate()
lifecycle method instead, only available for class components.
For functional components, useEffect()
can effectively replace all lifecycle hooks, including componentDidUpdate()
. You only have to customize the dependency array.
For instance, if your state has an age
property, and you want to check its value once the state is updated, useEffect()
hook would look like this:
useEffect(()=>console.log(`doing something with ${this.state.age}`), [age])
Irakli is a writer who loves computers and helping people solve their technical problems. He lives in Georgia and enjoys spending time with animals.
LinkedIn