Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can we implement componentWillUnmount using react hooks?

The method componentWillUnmount() is invoked immediately before a component is unmounted and destroyed. If we use useEffect with an empty array ([]) as the second argument and put our function in return statement it will be executed after the component is unmounted and even after another component will be mounted. This is done for performance reasons as far as I understand. In order not to delay rendering.

So the question is - how can we call some function using hooks before a component gets unmounted?

What I am trying to do is an application which saves user's input as he types (without submitting form). I use setInterval to save updated text every N seconds. And I need to force save updates before the component will unmount. I don't want to use prompt by react router before navigating. This is an electron application. I appreciate any thoughts or advice on how to implement such functionality.

Update

Unfortunately, Effects with Cleanup run after letting the browser paint. More details can be found here: So What About Cleanup?. It basically means that cleanup is run after a component is unmounted and it is not the same as executing code in componentWillUnmount(). I can clearly see the sequence of calls if I put console.log statements in the cleanup code and in another component. The question is whether we can execute some code before a component is unmounted using hooks.

Update2

As I can see I should better describe my use case. Let's imagine a theoretical app which holds its data in a Redux store. And we have two components with some forms. For simplicity, we don't have any backend or any async logic. We use only Redux store as data storage.

We don't want to update Redux store on every keystroke. So we keep actual values in the local component's state which we initialize with values from the store when a component mounts. We also create an effect which sets up a setInterval for 1s.

We have the following process. A User types something. Updates are stored in the local component state until our setInterval callback is called. The callback just puts data in the store (dispatches action). We put our callback in the useEffect return statement to force save to store when the component gets unmounted because we want to save data to store in this case as soon as possible.

The problem comes when a user types something in the first component and immediately goes to the second component (faster than 1s). Since the cleanup in our first component will be called after re-rendering, our store won't be updated before the second component gets mounted. And because of that, the second component will get outdated values to its local state.

If we put our callback in componentWillUnmount() it will be called before unmounting and the store will be updated before the next component mounts. So can we implement this using hooks?

like image 829
Georgy Nemtsov Avatar asked Apr 21 '19 19:04

Georgy Nemtsov


People also ask

How do you implement componentWillUnmount in React Hooks?

How to use componentWillUnmount with react hooks? For this task, we will useEffect hook provided by React JS and call our subscription for event or API inside useEffect and do the cleanup of that particular task inside useEffect hook itself.

How do you implement componentWillUnmount?

How to manage componentWillMount with useEffect. To understand how we can use componentWillUnmount, first we need to look at how the component manages mounting with useEffect. If we pass an empty array as the second argument, it tells useEffect to fire on component load. This is the only time it will fire.

Which is the equivalent React hook to componentWillUnmount?

If you're familiar with React class lifecycle methods, you can think of useEffect Hook as componentDidMount , componentDidUpdate , and componentWillUnmount combined. There are two common kinds of side effects in React components: those that don't require cleanup, and those that do.

How does componentWillUnmount work in React application?

ReactJS – componentWillUnmount() MethodThis method is called during the unmounting phase of the React Lifecycle, i.e., before the component is destroyed or unmounted from the DOM tree. This method is majorly used to cancel all the subscriptions that were previously created in the componentWillMount method.


4 Answers

componentWillUnmount can be simulated by returning a function inside the useEffect hook. The returned function will be called just before every rerendering of the component. Strictly speaking, this is the same thing but you should be able to simulate any behaviour you want using this.

useEffect(() => {
  const unsubscribe = api.createSubscription()
  return () => unsubscribe()
})

Update

The above will run every time there is a rerender. However, to simulate the behaviour only on mounting and unmounting (i.e. componentDidMount and componentWillUnmount). useEffect takes a second argument which needs to be an empty array.

useEffect(() => {
  const unsubscribe = api.createSubscription()
  return () => unsubscribe()
}, [])

See a more detailed explanation of the same question here.

like image 177
thecartesianman Avatar answered Oct 08 '22 09:10

thecartesianman


The question here is how do you run code with hooks BEFORE unmount? The return function with hooks runs AFTER unmount and whilst that doesn’t make a difference for most use cases, their are some where it is a critical difference.

Having done a bit of investigation on this, I have come to the conclusion that currently hooks simply does not provide a direct alternative to componentWillUnmount. So if you have a use case that needs it, which is mainly for me at least, the integration of non-React libs, you just have to do it the old way and use a component.

Update: see the answer below about UseLayoutEffect() which looks like it may solve this issue.

like image 24
David Bradshaw Avatar answered Oct 08 '22 09:10

David Bradshaw


Since the introduction of the useLayoutEffect hook, you can now do

useLayoutEffect(() => () => {
  // Your code here.
}, [])

to simulate componentWillUnmount. This runs during unmount, but before the element has actually left the page.

like image 6
Frank Avatar answered Oct 08 '22 09:10

Frank


I agree with Frank, but the code needs to look like this otherwise it will run only on the first render:

useLayoutEffect(() => {
    return () => {
        // Your code here.
    }
}, [])

This is equivalent to ComponentWillUnmount

like image 4
Simen L Avatar answered Oct 08 '22 08:10

Simen L