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

Renders not batched consistently since 3.3.11 #10136

Closed
KaelWD opened this issue Jan 16, 2024 · 2 comments
Closed

Renders not batched consistently since 3.3.11 #10136

KaelWD opened this issue Jan 16, 2024 · 2 comments

Comments

@KaelWD
Copy link
Contributor

KaelWD commented Jan 16, 2024

Vue version

3.3.11

Link to minimal reproduction

https://play.vuetifyjs.com/#eNqFkMEKgkAQhl9lmEsFqZhBIBp06QXqlh1MVxJcd9ld9yK+e7OuQQTRbX6+b4d/9jaiVlV0kjK0A8MUM8O47ErDjkUPkNmglHIe52DKhwYbcFGzLi+QYoELfXNIbdkNjGhM7NwqbbJoJj/FHYkXVom+/mcmZF6frfoSl6R9Zwq+dBZ9HENRV6qVBjQzg7+p5VIoAyMo1sAEjRIcVvQPK6cDUCNtwBXInbGON26n30LvcdpiEiZhHKMb9uEB7y92HWkI

Steps to reproduce

Click the second tab

What is expected?

There should be an animation on the tab underline.

What is actually happening?

No animation, the first tab re-renders before the second one gets the update event.

System Info

No response

Any additional comments?

vuetifyjs/vuetify#18892

https://github.com/vuetifyjs/vuetify/blob/fa5cccbdc9869eed397940574c3f6aaf144d7b31/packages/vuetify/src/components/VTabs/VTab.tsx#L60 expects that the DOM has not been updated yet

Bisected to #7181

@yyx990803
Copy link
Member

yyx990803 commented Jan 18, 2024

This is a difficult one - the fix in #7181 addresses an important issue, where watchers (pre by default) are firing for components that are unmounted in the same flush cycle.

However, this does introduce a change in the way pre-watchers interact with component updates:

  • Before the change: pre-watchers, even in child components, are fired before all component updates.

  • After the change: pre-watchers are fired before the owner component and its descendants' updates, but it will now be called after the parent component's update.

The post-change behavior is necessary for avoiding the "watcher firing for unmounted components" issue, because we can't know if the component is going to be unmounted until the parent has updated.

Vuetify here is relying on the before-change behavior: VBtn as a child, via the useGroupItem composable, is watching for its isSelected state, and emitting an event to the parent VTabs component, where the parent expects the DOM to not have been updated yet. A rather straightforward workaround for Vuetify is to make the watcher in useGroupItem sync instead.

So technically, the change in #7181 is a breaking change. The trade-off here is between:

  1. (old behavior) Let watchers fire for components unmounted in the same tick. This is probably quite easy to run into and not obvious to the users on how to workaround it.

  2. (new behavior) Watchers in a component unmounted in the same tick won't fire anymore, but they also now fire after parent updates. This only affects cases where a child pre-watcher expects to be fired before parent DOM updates. IMO this is a less common edge case as it should be in general avoided for a child component to care about parent DOM. In rare cases where this is needed, a sync watcher can be used instead.

IMO (2) is the more reasonable option here.

yyx990803 added a commit to vuejs/docs that referenced this issue Jan 18, 2024
@yyx990803
Copy link
Member

Updated relevant docs section to provide more details for the current behavior: vuejs/docs@80e2128

Closing since there is a simple workaround for Vuetify.

@yyx990803 yyx990803 closed this as not planned Won't fix, can't repro, duplicate, stale Jan 18, 2024
@github-actions github-actions bot locked and limited conversation to collaborators Feb 2, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants