Skip to content
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

(programmatically added) destroyed hooks retain on new instances #10458

Open
pimlie opened this issue Aug 30, 2019 · 11 comments
Open

(programmatically added) destroyed hooks retain on new instances #10458

pimlie opened this issue Aug 30, 2019 · 11 comments

Comments

@pimlie
Copy link

pimlie commented Aug 30, 2019

Version

2.6.10

Reproduction link

https://jsfiddle.net/h86atdq4/

Steps to reproduce

Open linked jsfiddle, open console and click toggle.

What is expected?

That the logged destroyed hook count is always 0 similar to the other hooks

What is actually happening?

The destroyed hook count keeps incrementing as it seems to retain hooks from already destroyed components


Note: I didnt check if this also happens with destroyed hook defined on the component itself

@sqal
Copy link
Contributor

sqal commented Sep 4, 2019

I wouldn't consider it a bug. You are modifying component's options before component's instance is created. If you need to programmatically add some lifecycle hook, you should do that in created hook using $on('hook:xxx) pattern. I do not know why but it is not properly documented so not everyone knows about it. Example usage:

created() {
  this.$on('hook:mounted', () => {
    // do something when component is mounted
  })
}

And you don't have to worry about cleaning up the events added this way in beforeDestroy hook, Vue will handle it for you

@pimlie
Copy link
Author

pimlie commented Sep 4, 2019

Very interesting, did not know this indeed. I had also asked this on Vue-land discord but unfortunately to no avail.

@sirlancelot
Copy link

sirlancelot commented Sep 4, 2019

You shouldn't write to this.$options. It is for reading only. If you want to attach hooks, you should do so using the public API this.$on() or this.$once(). To listen to a lifecycle hook using the event system, you can prefix it with hook: like so: this.$on("hook:mounted", () => {})

@pimlie
Copy link
Author

pimlie commented Sep 4, 2019

Unfortunately a vue core team member told me on discord that hook: is not a public API thus its not officially supported and shouldnt be relied on. Hence why its not documented.

So still looking for the official way to programmatically add lifecycle hooks.

@posva
Copy link
Member

posva commented Sep 5, 2019

To clarify, writing to this.$options in a beforeCreate hook is a very common way to manipulate options and it's used by many many plugins, it's not read-only, at least, in beforeCreate as it can still have an impact

@sirlancelot
Copy link

It's worth pointing out that the hook: syntax is documented appropriately under Handling Edge Cases: Programmatic Event Handlers.

@pimlie
Copy link
Author

pimlie commented Feb 25, 2020

It turns out (as found by @Remcoman with this jsfiddle https://jsfiddle.net/c61xL8ar/2/) that the memory leak occurs on any programmatically added lifecycle hook if the component you are adding them to already list those lifecycle hooks. Ie in the updated jsfiddle the AComponent already has a mounted hook, the BComponent already has a created hook. Both are being retained now.

@posva Does this mean its a bug or that we should use hook events anyway?

@sirlancelot
Copy link

sirlancelot commented Feb 25, 2020

It turns out (as found by @Remcoman with this jsfiddle https://jsfiddle.net/c61xL8ar/2/) that the memory leak occurs on any programmatically added lifecycle hook if the component you are adding them to already list those lifecycle hooks. Ie in the updated jsfiddle the AComponent already has a mounted hook, the BComponent already has a created hook. Both are being retained now.

Once again, that fiddle is paving over an object on this.$options. Don't do that. It is a Vue internal property.

@pimlie
Copy link
Author

pimlie commented Feb 26, 2020

@sirlancelot Please read this comment #10458 (comment) and read this vuejs/v2.vuejs.org#2247

Although I appreciate your time responding to this issue, there is conflicting information here and therefore I am asking the Vue core-team what I should do.
As a library maintainer I am unable to use a feature when I was specifically told not to use it. Not unless a go-ahead has been given to do so anyway. You might not agree with this approach, but you should at least respect it as Im only trying to do my due diligence here.

@sirlancelot
Copy link

Understandable. I was rather short in my previous post, and I apologize. I am going to guess that the "has workaround" was added in regards to using $on() & $once() with the hook: prefix.

@guastallaigor
Copy link

Hello, is there any way to use this workahound ($once()) in Vue 3.x?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants