Last updated: Apr 7, 2024
Reading timeยท3 min
Use the useEffect
hook to wait for the state to update in React. You can add
the state variables you want to track to the hook's dependencies array and the
function you pass to useEffect
will run every time the state variables
change.
import {useEffect, useState} from 'react'; const App = () => { const [count, setCount] = useState(0); useEffect(() => { console.log('useEffect ran. count is: ', count); }, [count]); // ๐๏ธ Add state variables you want to track return ( <div> <h2>Count: {count}</h2> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); }; export default App;
The code sample shows how to listen for state changes in React.
The useState hook is used to track the state in the component.
const [count, setCount] = useState(0);
The second parameter we passed to the useEffect hook is an array of dependencies.
useEffect(() => { console.log('useEffect ran. count is: ', count); }, [count]); // ๐๏ธ Add state variables you want to track
We added the count
state variable to the hook's dependencies array, so any
time count
changes, the logic in our useEffect
hook will rerun.
Anytime the button is clicked, the value of count
changes and the function we
passed to useEffect
is invoked.
useEffect
hook.Note that the useEffect
hook is also invoked when the component mounts.
I've also written an article on how to update the state when props change.
useEffect
on the initial renderIf you don't want to run the logic in your useEffect
hook on the initial
render, but only when the specific state variable changes, use a ref
to return
early on the initial render.
import {useEffect, useState, useRef} from 'react'; const App = () => { const [count, setCount] = useState(0); const isFirstRender = useRef(true); useEffect(() => { if (isFirstRender.current) { isFirstRender.current = false; return; // ๐๏ธ Return early if initial render } console.log('useEffect ran. count is: ', count); }, [count]); // ๐๏ธ Add state variables you want to track return ( <div> <h2>Count: {count}</h2> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); }; export default App;
The code sample listens for state changes of the count
variable but skips the
initial render.
We used a ref to exit early when the
useEffect
hook is run on mount.
Use this approach if you want to listen for state changes but need to skip the first render.
If you update a specific state variable in the useEffect
hook and the variable
is present in the hook's dependencies array, you would
cause an infinite re-render loop.
Here is an example that demonstrates this issue.
import {useEffect, useState} from 'react'; const App = () => { const [count, setCount] = useState(0); useEffect(() => { console.log('useEffect ran. count is: ', count); setCount(count + 1); // ๐๏ธ This causes infinite loop }, [count]); return ( <div> <h2>Count: {count}</h2> <button onClick={() => setCount(count + 1)}> Increment </button> </div> ); }; export default App;
The issue is that we have added the count
state variable to the dependencies
array of the useEffect
hook, but we are also updating count
in the hook.
Every time useEffect
is run, the value for the count
variable is changed,
which re-runs the hook again because count
is in its dependencies array.
If you need to run a React hook when the component unmounts, click on the link and follow the instructions.