useEffect cleanup on unmount with dependencies

Viewed 1035

I need a way to run a React useEffect cleanup function on component unmount only, but using the latest state from the component.

Consider the following example:

const [foo, setFoo] = useState(true)

useEffect(() => {
  return () => {
    if(foo) 
      console.log("T") 
    else
      console.log("F")
  }
}, [])

...later:

setFoo(false)

In this example, "T" will be printed on unmount even though the current value of foo is false.

Your first thought might be to add foo to the dependency array of the effect, but this causes the effect to clean up twice: once when the state changes to false (printing "T"), and once when the component unmounts (printing "F").

I would like it only to print "F", once the component unmounts.

1 Answers

One solution to this problem is to use useRef as follows:

const [foo, setFoo] = useState(true)

// Store value of foo and keep it up-to-date.
const fooRef = useRef(foo)
useEffect(() => fooRef.current = foo, [foo]);

// Use ref value.
useEffect(() => {
  return () => {
    if(fooRef.current) 
      console.log("T") 
    else
      console.log("F")
  }
}, [])

...

setFoo(false)
Related