In class-based React components, we can pass a callback into the 2nd argument of setState
to run code when a state is updated with setState
.
With React hooks, we no longer have the setState
method.
Instead, we use state updater functions created with the useState
hook to update states.
This means we’ve to find new ways to run code after a state is updated.
In this article, we’ll look at how to run async code after a state is updated in function components created with React hooks.
useEffect Hook
The useEffect
hook lets us commit side effects in our component code.
We can commit side effects in response to changes in one or more states.
To specify which state to watch, we pass an array of states we want to watch into the 2nd argument of useEffect
.
Then in the useEffect
callback we pass into the first argument, we can run code when the state in the 2nd argument changes since the callback in the first argument will be run when the state in the 2nd argument changes.
For instance, we can write:
import React, { useEffect, useState } from "react";
export default function App() {
const [loading, setLoading] = useState(false);
const [loading2, setLoading2] = useState(false);
useEffect(() => {
setTimeout(() => setLoading(true), 1000);
}, []);
useEffect(() => {
if (loading) {
setTimeout(() => setLoading2(true), 1000);
}
}, [loading]);
return (
<>
<div>{loading.toString()}</div>
<div>{loading2.toString()}</div>
</>
);
}
We have 2 states, loading
and loading2
, which we updated inside the useEffect
callbacks.
In the first useEffect
callback, we call setTimeout
with a callback that calls setLoading
to set loading
to true
after 1000 milliseconds.
The empty array in the 2nd argument means that the useEffect
callback only runs when the component is being mounted.
Next, we call useEffect
again with a callback that gets the loading
value.
In the callback, we check if loading
is true
,
If it is, then we call setTimeout
with a callback to call setLoading2
to set loading2
to true
after 1000 milliseconds.
In the 2nd argument, we have an array that has the loading
state.
This means whenever the loading
state changes, the useEffect
callback will run.
This means useEffect
lets us run code on state updates.
In the JSX, we render the values of each state.
And we should see them become true
one after the other.
Conclusion
We can run async code after state changes by calling the useEffect
hook to watch the value of a state by passing the states we want to watch into the array in the 2nd argument of useEffect
.
Then we can run code according to the value changes in the useEffect
callback.