Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

componentWillUnmount with React useEffect hook

How can the useEffect hook (or any other hook for that matter) be used to replicate componentWillUnmount?

In a traditional class component I would do something like this:

class Effect extends React.PureComponent {     componentDidMount() { console.log("MOUNT", this.props); }     componentWillUnmount() { console.log("UNMOUNT", this.props); }     render() { return null; } } 

With the useEffect hook:

function Effect(props) {   React.useEffect(() => {     console.log("MOUNT", props);      return () => console.log("UNMOUNT", props)   }, []);    return null; } 

(Full example: https://codesandbox.io/s/2oo7zqzx1n)

This does not work, since the "cleanup" function returned in useEffect captures the props as they were during mount and not state of the props during unmount.

How could I get the latest version of the props in useEffect clean up without running the function body (or cleanup) on every prop change?

A similar question does not address the part of having access to the latest props.

The react docs state:

If you want to run an effect and clean it up only once (on mount and unmount), you can pass an empty array ([]) as a second argument. This tells React that your effect doesn’t depend on any values from props or state, so it never needs to re-run.

In this case however I depend on the props... but only for the cleanup part...

like image 966
ChrisG Avatar asked Mar 13 '19 10:03

ChrisG


People also ask

How do I write componentWillUnmount in useEffect?

Using componentWillUnmount with useEffectuseEffect(() => { window. addEventListener("mousemove", () => {}); return () => { window. removeEventListener("mousemove", () => {}) } }, []); That's it.

Can we use async await with the useEffect hook?

Either way, we're now safe to use async functions inside useEffect hooks. Now if/when you want to return a cleanup function, it will get called and we also keep useEffect nice and clean and free from race conditions. Enjoy using async functions with React's useEffect from here on out!

How can we use useEffect as componentDidMount componentDidUpdate and componentWillUnmount?

useEffect runs on every render, it is a combination of componentDidUpdate, componentDidMount and ComponentWillUnmount. If we add an empty array in useEffect it runs just when the component mounted. It is because useEffect will compare the array you passed to it.

Does useEffect run on unmount?

We should see 5 “Use Effects” logged to the console, one when the component is first rendered, the one for each button click, meaning that the useEffect doesn't currently run on unmount.


1 Answers

You can make use of useRef and store the props to be used within a closure such as render useEffect return callback method

function Home(props) {   const val = React.useRef();   React.useEffect(     () => {       val.current = props;     },     [props]   );   React.useEffect(() => {     return () => {       console.log(props, val.current);     };   }, []);   return <div>Home</div>; } 

DEMO

However a better way is to pass on the second argument to useEffect so that the cleanup and initialisation happens on any change of desired props

React.useEffect(() => {   return () => {     console.log(props.current);   }; }, [props.current]); 
like image 99
Shubham Khatri Avatar answered Sep 22 '22 05:09

Shubham Khatri