Skip to content

Watch not triggered by changes during rendering #2730

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

Closed
skirtles-code opened this issue Dec 4, 2020 · 6 comments
Closed

Watch not triggered by changes during rendering #2730

skirtles-code opened this issue Dec 4, 2020 · 6 comments

Comments

@skirtles-code
Copy link
Contributor

Version

3.0.4

Reproduction link

Steps to reproduce

I've provided two examples but I believe they're both effectively the same problem. In both cases you just need to click the button and then check the logging.

Notice that the logging from the watch gets behind. The new value isn't logged until the following button click.

The first example uses ref attributes to update a reactive ref. The second example uses an updated hook to achieve a similar effect.

The workaround in both cases is to set flush: 'post'. However, that shouldn't be necessary. Any watchers with flush: 'pre' that are still in the queue at the end of rendering should be processed immediately. I haven't checked the code but it may just be a case of going through another rendering cycle when there are outstanding watchers rather than specifically flushing the pre-watchers.

What is expected?

All remaining watchers should be called by the time the rendering loop completes.

What is actually happening?

The watcher isn't called until the next time rendering is triggered.

@asv7c2
Copy link

asv7c2 commented Dec 13, 2020

Looks like it by design. doc

@skirtles-code
Copy link
Contributor Author

@Asv1 I don't see anything in the docs to suggest that this is by design.

Triggering a flush: 'pre' watcher during rendering is an awkward case. There is some wiggle room for deciding what the 'correct' behaviour should be but I don't think it makes sense to leave unflushed items in the queue.

@asv7c2
Copy link

asv7c2 commented Dec 13, 2020

When a user effect is queued, it is by default invoked before all component update effects

With template refs you always must use flush post because refs assigned after rendering.

@xinchao-zhang
Copy link

xinchao-zhang commented May 21, 2021

@Asv1 I don't see anything in the docs to suggest that this is by design.

Triggering a flush: 'pre' watcher during rendering is an awkward case. There is some wiggle room for deciding what the 'correct' behaviour should be but I don't think it makes sense to leave unflushed items in the queue

Absolutely, and I don't think there is anything awkward in triggering a flush: 'pre' watcher during rendering. After all, you are not directly triggering a watcher, you are just mutating reactive data and expect the reactive system to do its job.

To me, whether a watch effect should be executed is the definition/contract of watchEffect - it should be, and mostly is, very simple: the effect will run whenever the reactive data it depends on changes.

However, when and in what order effects are actually executed is an implementation detail. It is totally fine for the scheduler to queue an effect to an later (post or next pre) stage, but it still needs to execute the effect eventually.

When a user effect is queued, it is by default invoked before all component update effects

With template refs you always must use flush post because refs assigned after rendering.

I don't think the document is suggesting it is the golden rule for template ref watchers to always be post flush. Without flush: 'post' the watchEffect normally triggers fine (the abnormal cases are this issue and the issues it links to). You only need flush: 'post' when your effect needs to access the updated DOM as I understand. In other words, flush: 'post' is not to influence whether an effect will be triggered, but when it is triggered.

@skirtles-code
Copy link
Contributor Author

I think this will be fixed by b57e995, which is available in 3.1.0-beta.5.

@HcySunYang
Copy link
Member

Fixed in b57e995

YJL626 added a commit to YJL626/vueuse that referenced this issue Jun 7, 2021
in some cases useTitle doesn't work .
it has to  work in nextick 

https://codepen.io/yjl626/pen/rNyKVZW
vuejs/core#2730

set watch option as flush: 'post' can fixed it
I think it's a reliable option in this function
@github-actions github-actions bot locked and limited conversation to collaborators Oct 20, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants