How to Listen for State changes in React

avatar

Borislav Hadzhiev

Tue Apr 19 20222 min read

Listen for State changes in React #

Use the useEffect hook to listen for state changes in React. You can add the state variables you want to track to the hook's dependencies array and the logic in your useEffect hook will run every time the state variables change.

App.js
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> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); }; export default App;

The second parameter we passed to the useEffect hook is an array of dependencies. The function we passed to the hook will get invoked any time one of the dependencies changes.

listen for state changes

We added the count state variable to the hook's dependencies array, so any time count changes, the logic in our useEffect hook will re-run.

Add all of the state variables you want to track to the dependencies array of your useEffect hook.

Note that the hook is also invoked when the component mounts.

If 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.

App.js
import {useEffect, useRef, useState} from 'react'; const App = () => { const [count, setCount] = useState(0); const isFirstRender = useRef(true); useEffect(() => { if (isFirstRender.current) { isFirstRender.current = false; return; // 👈️ return early if first render } console.log('useEffect ran. count is: ', count); }, [count]); // 👈️ add state variables you want to track return ( <div> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); }; export default App;

We used a ref to exit early when the useEffect hook is ran on mount.

listen for state changes skip first render

Use this approach if you want to listen for state changes but need to skip the first render.

It should be noted that 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.

App.js
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> <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 ran, the value for the count variable is changed, which re-runs the hook again because count is in its dependencies array.

Use the search field on my Home Page to filter through my more than 1,000 articles.