Updating state when props change in React

avatar
Borislav Hadzhiev

Last updated: Apr 7, 2024
3 min

banner

# Updating state when props change in React

To update state when props change in React:

  1. Pass the props as dependencies to the useEffect hook.
  2. Every time the props change, the logic in useEffect is rerun.
App.js
import {useEffect, useState} from 'react'; function Child({parentCount}) { const [childCount, setChildCount] = useState(0); useEffect(() => { setChildCount(parentCount * 2); console.log('useEffect logic ran'); }, [parentCount]); // ๐Ÿ‘ˆ๏ธ Add props as dependencies return ( <div> <button>Child count {childCount}</button> </div> ); } export default function Parent() { const [parentCount, setParentCount] = useState(0); return ( <div> <button onClick={() => setParentCount(current => current + 1)} > Parent count: {parentCount} </button> <hr /> <Child parentCount={parentCount} /> </div> ); }

update state on props change

The code for this article is available on GitHub

We used the useEffect hook to update the state of a component when its props change.

App.js
useEffect(() => { setChildCount(parentCount * 2); console.log('useEffect logic ran'); }, [parentCount]); // ๐Ÿ‘ˆ๏ธ Add props as dependencies

The logic in the useEffect hook is rerun every time one of its dependencies changes.

Every time the parentCount prop changes, the useEffect hook is rerun and we use the setChildCount function to update the state.

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

Note that the function we passed to the useEffect hook is also invoked on the initial render.

# Don't run the logic in useEffect on the initial render

If you don't want to run the logic in your useEffect hook on the initial render, but only when the specific prop changes, use a ref to return early on the initial render.

App.js
import {useEffect, useRef, useState} from 'react'; function Child({parentCount}) { const [childCount, setChildCount] = useState(0); const isFirstRender = useRef(true); useEffect(() => { if (isFirstRender.current) { isFirstRender.current = false; return; // ๐Ÿ‘ˆ๏ธ Return early if first render } setChildCount(parentCount * 2); console.log('useEffect logic ran'); }, [parentCount]); return ( <div> <button>Child count {childCount}</button> </div> ); } export default function Parent() { const [parentCount, setParentCount] = useState(0); return ( <div> <button onClick={() => setParentCount(current => current + 1)}> Parent count: {parentCount} </button> <hr /> <Child parentCount={parentCount} /> </div> ); }

dont run logic in use effect on the initial render

The code for this article is available on GitHub

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

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

I've also written a detailed guide on how to call a child function from a parent component.

# Avoiding infinite re-render loops

It should be noted that if you update the value of a prop and the prop 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'; function Child({parentCount, setParentCount}) { useEffect(() => { // ๐Ÿ‘‡๏ธ This causes an infinite loop setParentCount(current => current + 1); console.log('useEffect logic ran'); }, [parentCount, setParentCount]); // ๐Ÿ‘ˆ๏ธ parentCount is a dependency return ( <div> <button>Parent count {parentCount}</button> </div> ); } export default function Parent() { const [parentCount, setParentCount] = useState(0); return ( <div> <Child setParentCount={setParentCount} parentCount={parentCount} /> </div> ); }

avoiding infinite re render loops

The code for this article is available on GitHub

The issue is that we added the parentCount prop to the hook's dependencies array but we are also updating its value in the hook.

Every time useEffect is run, the value of parentCount is changed, which re-runs the hook again because parentCount is in its dependencies array.

I've also written an article on how to update a component's state on click.

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.

Copyright ยฉ 2024 Borislav Hadzhiev