React patterns: Run effect only if dependencies change
4 September 2022 (Updated 19 September 2022)
On this page
Note: You can use react-use ‘s useUpdateEffect (source) hook to do this instead of rolling out your own hook.
In a nutshell
If you want to run an effect only when the dependencies are updated but not on initial render, you’ll have to do something like this:
import React, { useEffect, useState } from 'react'
import useIsFirstRender from '../lib/hooks/useIsFirstRender'
const UseEffectOnlyWhenDependenciesUpdate: React.FC = () => {
const isFirstRender = useIsFirstRender()
const [name, setName] = useState('')
useEffect(() => {
if (!isFirstRender) {
console.log(`Name has changed to "${name}"`)
}
}, [isFirstRender, name])
function handleChange(event: React.ChangeEvent<HTMLInputElement>) {
setName(event.target.value)
}
return (
<>
<input
type="text"
placeholder="Name"
value={name}
onChange={handleChange}
className="mb-2"
/>
</>
)
}
export default UseEffectOnlyWhenDependenciesUpdate
Notice the if (!isFirstRender) check inside the useEffect. If you don’t include this check, the effect will also run on initial render.
The useIsFirstRender hook can look something like this:
import { useRef } from 'react'
export default function useIsFirstRender() {
// Assume first render by default
const isFirstRender = useRef(true)
if (isFirstRender.current) {
// On first render, set isFirstRender flag to false
// so that future renders know we've already rendered
isFirstRender.current = false
return true
}
return isFirstRender.current
}
Other notes
- Conceptually, you can think of the dependencies array as arguments to your
useEffectfunction – you should list everything that the effect depends on to do its work.
Sources
Tagged:
React recipes
Thanks for your comment 🙏. Once it's approved, it will appear here.
Leave a comment