-
Notifications
You must be signed in to change notification settings - Fork 47.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
componentDidUnmount functionality (in addition to componentWillUnmount) #6424
Comments
That is an interesting use case, but I'm not yet convinced that it justifies an additional lifecycle method, because I think there is an equally viable alternative for your service deconstruction. I'm curious if you would agree... What if a Service (as created by the parent) receives the information needed to open the required connection/resource, but doesn't actually open the resource until a child component starts listening. The service then closes the connection/resource when the last child stops listening. This means that the parent never needs to destroy the service, and normal garbage collection rules can apply. Would this approach work for you? |
It's not really a Service per se, it's any object we use that follows the Observer pattern. It's just it would be good to have componentDidUnmount because then if Parent doesn't destroy the service then you're relying on Children to stop listening properly, which may cause leaks. |
I think my previous comment above still holds true for most implementations of the Observer pattern. Just If children don't stop listening properly, you've likely got bigger problems. It is common for data to be provided by a static parent and children to enter/exit throughout the lifetime of the application, so you'll likely be leaking anyway. |
AFAIK, without a symmetrical hook for server-side rendering it is impossible to release any resources (unsubscribe listeners) used in |
Isn’t the current recommendation to never hold onto any resources in |
By the way I’m interested in having this method too. When a child is subscribed to a Flux store, and the parent fires an action in The child doesn’t know that it should unsubscribe because the parent is cleaning up. There is no way for the parent to safely clean up any external state the child may depend upon. If we had |
Yeah at the moment I had to include a bit ugly workarounds for the cases where |
@gaearon Yes, that was the original post/request almost verbatim. But is there a reason the approach in #6424 (comment) is insufficient? Seems like a parent can always create an object that lazy-initializes any required resource, and cleans it up when all users of those resources are done. Is it just that there is a little additional boilerplate? Is there a particular resource you have in mind that would exemplify the use case? |
In this case, I’m referring to some piece of data in a Flux store that the parent cleans up. I don’t use this pattern myself but some consumers of React Redux bindings do, and I recently introduced a regression related to this use case (reduxjs/react-redux#351). I wish I could tell people to use a different lifecycle hook for tearing down the data rather than being careful in the container implementation and having to implement workarounds like this: reduxjs/react-redux@ea53d6f. Asking them to pass something like |
cc @sebmarkbage |
By the way I briefly chatted with @sebmarkbage today about this, and my particular problem would be solved by delaying some calls until |
Unless the object cleans itself up (not ideal, and sometimes not available as an option, e.g. parent provides set of listeners (children), then listeners get unmounted, then parent provides another set of listeners), the parent can't clean the object up because the parent gets unmounted before the children. Switching to Flux/Redux etc. is not for everyone. |
Why is it not ideal? When is it not an option (I'm fairly certain it is always an option, because you can use simple reference counting to determine when to cleanup)?
Why does the parent need to do any cleanup? Why doesn't the datastore cleanup when the last child unmounts? |
@jimfb it's not ideal because you are basically re-encoding the logic for unmounting the tree of components from the deepest child up in your data type, which is just unnecessary error prone boilerplate. I want to clean up my component after my children have unmounted - in principle this seems like a very reasonable thing to want to do, and I don't think it's reasonable to have to rebuild this lifecycle method externally. Additionally, you do not always have the option of rewriting the data store - sometimes you are interfacing with legacy code! (This is my current personal situation) |
We also need this method to be implemented |
mega +1 for this one, the problem is perfectly explained by @gaearon.
|
I think I found a hacky way to do this by abusing the ref prop. When the ref prop is passed a function it calls this function passing you a ref to the dom element on mount and passing you null on unmount. By hijacking this function I was able to build a wrapper component that renders its children in a div and then an extra span/div element immediately after the children. The extra span/div has a ref prop set to a function that will bubble up to its parent if its called with a null (meaning the element has been unmounted). I then use this wrapper to sit between my parent and children components, using its onUnmount event in the parent to let me know after the children are gone so I can do the cleanup I need. here is a link to an example and below is the code:
In my example code, the parent renders a button and a wrapped set of children that are mounted and unmounted on click. When the unmount happens you will see in the console that all three children's componentWillUnmount are called before the unload wrapper calls back to the parent, thus letting the parent know after its children have been fully removed. So far this works but have not tested fully. My only concern is the order of the unmount sequence react does, I am assuming that on unmount, react processes each element, then loops children in order sequentially, which allows my unload wrapper to work. If it does anything an parallel then I might run into issues. If anybody can see if any major flaws in this please let me know! |
The existing This makes it hard to dispose of shared resources created by the parent and used by the children, since the resources may still be in use by the children when the parent's cWU method is invoked. |
Closing as React's design is moving away from class-based lifecycle methods |
React does not seem to have a `componentDidUnmount` lifecycle method and there is no mention of it in the react docs. As far as I can tell, this was meant to be `componentWillUnmount`. See also this issue on the react github: facebook/react#6424
It would be great if it was possible to run some code after the component actually unmounted. This is useful where you consider the following:
The above will throw exception during Child componentWillUnmount since Parent gets unmounted first so Service is already destroyed.
If there existed componentDidUnmount the Service can be destroyed after the children are unmounted, i.e.
The text was updated successfully, but these errors were encountered: