React: Document the use of setState in componentWillUnmount

Created on 29 Jan 2018  路  11Comments  路  Source: facebook/react

Do you want to request a feature or report a bug?

Feature

What is the current behavior?

Excerpt from documentation:

componentWillUnmount() is invoked immediately before a component is unmounted and destroyed. Perform any necessary cleanup in this method, such as invalidating timers, canceling network requests, or cleaning up any subscriptions that were created in componentDidMount().

https://reactjs.org/docs/react-component.html

The docs don't mention if setState can be used in componentWillUnmount.

Consider the following example where the state.showGreeting is undone by timer over time. But since the timer has to be invalidated in componentWillUnmount there no other place to reset the state:

class HelloWorld extends Component {
  state = {
    showGreeting: false
  };

  onClick() {
    this.setState({ showGreeting: true })

    this._timer = setTimeout(() => this.setState({ showGreeting: false }), 3000)
  }

  componentWillUnmount() {
    clearTimeout(this._timer)

    // is it legal?
    this.setState({ showGreeting: false })
  }
}

Is it legal to call setState from componentWillUnmount? Given that it can be asynchronous it feels that setState may not be invoked until after component is actually unmounted which may produce a warning in my understanding, until.. componentWillUnmount actually pumps up the state's dispatch queue manually to ensure that all state changes land in component before it's too late.

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem. Your bug will get fixed much faster if we can run your code and it doesn't have dependencies other than React. Paste the link to your JSFiddle (https://jsfiddle.net/Luktwrdm/) or CodeSandbox (https://codesandbox.io/s/new) example below:

What is the expected behavior?

Not sure

Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?

16.2 / Webkit

Question

Most helpful comment

No, it's not supported or useful. (Happy to take a PR documenting that)

I'm not sure what you're trying to achieve. If the component is being unmounted, there's no need to "reset" the state. A component can't be "resurrected" so if it gets unmounted, its state is irrelevant to the rest of the program.

All 11 comments

No, it's not supported or useful. (Happy to take a PR documenting that)

I'm not sure what you're trying to achieve. If the component is being unmounted, there's no need to "reset" the state. A component can't be "resurrected" so if it gets unmounted, its state is irrelevant to the rest of the program.

@gaearon aha makes sense. I had an impression that if I hold onto an instance of React component I can actually mount it conditionally. So I thought of didMount and willUnmount as when view appeared or about to disappear. I never did this actually but always assumed that somebody can thus to be a good citizen supported the clean up in the same fashion. Thanks for clarification.

I see. Is there anywhere in the docs we could've made this clearer?

No I think it makes sense now and "Reconciliation" guide explains the principle very well. RTFM is the key :) Not sure there has to be a mention about setState in willUnmount since there is no need to clean up the instance that's about to be dropped. Thank you once again!

Maybe we could add a notice in componentWillUnmount doc that once a component is unmounted, it can never be re-mounted.

I think that would be really useful @gaearon. With your explanation above it makes perfect sense why you'd not need to change the state in componentWillUnmount(), but I wrongly assumed the same as @pronebird.

Resurrecting this question because I had the same question when looking at the docs: https://reactjs.org/docs/react-component.html#componentwillunmount

I think a quick sentence stating not to use setState in this function would be helpful.

Do you want to send a PR to the docs? You probably have a better idea of what's missing :-)
The doc page contains an "Edit" link at the bottom.

What's the recommendation for something you only want to do when you unmount?

Say pushing the current timestamp for the last time the object was edited.

@meetbryce I'd say the one should "cancel" any code that may potentially reference the instance that's about to unmount, for instance: timers, network requests that may reference the component instance in their corresponding callbacks.

I had warning message Can't perform a React state update on an unmounted component. because I called setState on an unmounted component after data fetching promise resolve/reject.
Googling the issue I landed the docs:

An easy migration strategy for anyone upgrading their code to avoid isMounted() is to track the mounted status yourself. Just set a _isMounted property to true in componentDidMount and set it to false in componentWillUnmount, and use this variable to check your component鈥檚 status.

My action after reading the paragraph above was setting isMounted state to true/false in componentDidMount and componentWillUnmount respectively. But it didn't work.

Now I understand that setState in componentWillUnmount have no sense and I should create a cancellable promise to solve the issue. Maybe update the docs to avoid misunderstanding?

Was this page helpful?
0 / 5 - 0 ratings