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
useEffect
function – you should list everything that the effect depends on to do its work.
Sources
Tagged:
React patterns
Thanks for your comment 🙏. Once it's approved, it will appear here.
Leave a comment