A hook that runs only after a component is mounted
10 mins
-
"2023-01-25T00:00:00.000Z"
A hook that runs after the component is 'mounted'
Here is a hook that will will not run the supplied function on the first render:
import { useRef, useEffect, useState } from 'react'const useDidMountEffect = (func, deps) => {const isMounted = useRef(false)useEffect(() => {if (isMounted.current) func()else isMounted.current = true}, deps)// reset on unmount; in React 18, components can mount again// useEffect(() => {// isMounted.current = false// })}
You can use it like this:
export default function UseMountEffectExample() {const [toggle, setToggle] = useState(false)useEffect(() => {console.log('Running useEffect. Toggle Value: ', toggle)}, [toggle])useDidMountEffect(() => {// react please run me if 'key' changes, but not on initial renderconsole.log('Running useDidMountEffect. Toggle Value: ', toggle)}, [toggle])return (<div className="flex flex-col content-between"><button onClick={() => setToggle((prev) => !prev)}>Toggle</button><p>Toggle: {toggle ? 'true' : 'false'}</p></div>)}
Codepen here to play round with: https://codepen.io/rainkinz/pen/ZEMYaeN
Some notes on useEffect
useEffect
by default runs after the first render and after every update. React runs useEffect
after it has finished updating the DOM on render.
useEffect(() => {// do something when the component rendersreturn () => {// cleanup}})
In certain cases, applying the effect after every render might not be desirable. We can list arguments
that will cause useEffect
to fire if they have changed:
useEffect(() => {// do something when the component renders but only if count has changed}, [count])
The same thing was done in class components using prevProps
or prevState
in componentDidUpdate
remembering that the componentDidUpdate
lifecycle method is invoked during each render, except the first one. The componentDidMount
is only invoked once, after the first render.
componentDidUpdate(prevProps, prevState) {if (prevState.count !== this.state.count) {// do something when the component renders}}
Note that listing no arguments in the dependency array []
makes the effect and cleanup run only once, on mount and unmount.
useEffect(() => {// do something when the component mountsreturn () => {// cleanup on unmount}}, [])