-
-
Notifications
You must be signed in to change notification settings - Fork 8.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
Kept alive components still update (renders, watchers) while being deactivated #5386
Comments
Can it be confirmed at least that these behaviour are indeed bugs and not intended? From the layman's perspective they clearly are by the token that if someone wanted to keep the components rendering and watchers running they could use The current behaviour matches that of option 2. Since it is already achievable quite easily with the The documentation is rather vague on what the intended behaviour should be as it only really explains the behaviour as "cached". It explicitly says that the component state should be preserved (differentiating it from For me it looks like rendering, watchers or computed properties should be paused, otherwise we could simply just use Correct me, if I'm wrong pls! |
From my perspective, the rendering is not taken place as it's not rendered in the DOM tree, so it's not the same as
I also created a minimal playground locally but with Vue 2. From what I can tell, it works exactly the same as what @posva see in his playground. So I suspect maybe the behavior is intended and not a bug. Let me know if you have different ideas. :-) |
Hello,
Indeed if it's the same behavior as vue 2 then it might be intented, |
That is a good point. Thanks! If I look from this perspective than I can see these activity levels a component in theory could be in:
note 1: Achieving rendering to halt using note 2: The even bigger problem is: sometimes we need 5th state as well, but currently it is not achievable in any reasonably simple ways. In fact one can replace all calculated variables with watchers and make those watchers observe a bail-out variable to abort any updates when desired, but it is a huge overhead to do it this way, also it must be combined with the In fact the name "KeepAlive" suggests something other than 5th or 6th state, as 6th obviously cannot be considered "Alive" and 5th neither based on that Watchers, Calculated and Rendering are disabled. So implementing 3rd or 4th state under the name On the other hand if the explanation in the documentation says "Cached", why the component is called "Alive"? Further complicating the matters the associated component state is called "inactive", and the associated lifecycle hook is called "deactivated". I know it happens a lot that names evolve organically, but I'd suggest these 4 different names are adding to the confusion. Also the term "cached" would be the perfect terminology to differentiate 3rd and 5th state: In an ideal world I'd love to see convenient ways to do all 6 levels:
|
Now the terminology is hard to get right, because obviously existing names should be kept, also the same things may have different name from Component lifecycle perspective, documentation, developer experience representation etc. Anyway here's my take on trying to collect my thoughts:
note 3: These are the terms I found in Vue Dev Tools and the Documentation. note 4: IMHO, indeed. |
I would argue your 5th 'level' describes the most logical and expected behaviour of them all, especially when combining it with Suppose the user navigated from "home" to "about us". Why would any developer want:
Am I missing a very obvious use-case here? The current behaviour of |
@tafelnl , I think it relates to this #7286 pull request. I believe once this PR is merged. We will see this bug being fixed in vue-router soon. |
@yxchai I think that's a totally different issue to be honest. I am talking about pausing |
I tried pausing the effect in the keep-alive deactivate state in #9206. It can be achieved currently, but it is more difficult in vShow because vShow needs to execute the effect before it can determine whether to display it. |
The issue with keeping the state reactive is very much concerning the app's mode of operation. We are using |
I doubt that the current behavior will ever be changed because it would be a massive breaking change: there is no guarantee that there aren't projects that rely on reactivity continuing to work inside deactivated components. The very concept of KeepAlive implies that a component is added to the vDOM/DOM faster because it is kept in memory. If reactivity within deactivated components stops working, then when the component is added back to the vDOM/DOM, it would be almost like creating the component anew, as all computed properties would need to be recalculated and the vDOM/DOM re-rendered. Additionally, what should be done in situations where, for example, there is a watch in the component on a value from the Vuex store, and the component increments a counter every time this value changes? Should we remember all the changes and replay them upon reactivation of the component? This example is far-fetched, but in real applications, the logic can be much more complex. It must be admitted that in our project, we did indeed encounter situations where reactivity within deactivated components (in our case, entire pages) led to performance drops. We solve this with two custom composables: useActivatableEffect and computedActivatable. All reactivity inside useActivatableEffect is removed when the component is deactivated and recreated upon activation. We also use this for registering event listeners. The computedActivatable function uses useActivatableEffect internally to create a computed property that only recalculates when the component is active. I cannot share the code for these composables, mainly because we handle many different nuances related to SSR and hydration, and we also perform a lot of other necessary magic specific to our case. However, fundamentally, these are very simple functions. Here is an example implementation in the SFC Playground. |
@mefcorvi Thanks for the explanation. I was thinking of using I see that #9651 implements |
Version
3.2.30
Reproduction link
sfc.vuejs.org/
Steps to reproduce
What is expected?
What is actually happening?
After changing the page once, the Page One keeps rendering while being inactive
This has been confusing to many people but I couldn't find if this behavior is expected or not
This also means watchers are executed in deactivated branches
It also worth noting that the component being deactivated renders before being deactivated. Making it impossible to skip the render with likely incorrect data.
The text was updated successfully, but these errors were encountered: