Skip to content

Watch immediate: true and flush: 'post' don't compose well #14129

@camsteffen

Description

@camsteffen

Vue version

3.5

Link to minimal reproduction

https://play.vuejs.org/#eNp9Ul2L2zAQ/CuLXpyA60Dv+pI6gbYctKVfXPMoKMZex7rKK6EPJyX4v3clN9ejlHuzZmZXM2NdxBtrqymi2Irat07ZAB5DtHtJarTGBbiAw76E6PGAo9VNwPt0PjWhHWCG3pkRCt5QSJLUGvIBxl8sgd0/M6si48X69VU3NZpVvH6VMEl554rRElZr2O3hIgmWbRWjEStFhO794fMnnmNkQXl2LuGixhE7xXdtg4tYQq+jH7ZQWONDMa8l1ZslIWfjQ/jjjE8AtSIb2dCL0XSod1LwYin29Sbji6RTU/LKZHbE9GFQHvxgou6o4OIGcwJD0CvH4RxSh67e8BjP15sn94lSBM8V9OpYPXhDXH5OKkVrRqs0uq82KK5Iiu3SQeIarc3pY8ZywCveDtj+/A/+4M8Jk+KbQ49uQikeudC4I4aFvvv+Bc/8/UhyB1Gz+hnyHr3RMXlcZG8jdWz7iS67/ZCfkKLjwd+dA5K/hkpGk3LOeq474rtnov+1e1Pd5jn+5dzijwld2skF3lSvqpe3Yv4NrUPyGA==

Steps to reproduce

Write a watch with { immediate: true, flush: 'post' }.

What is expected?

The first call occurs after the first render. The DOM is always available in the callback.

What is actually happening?

The first call occurs synchronously. I can't assume the DOM is available in the callback. I need a workaround to invoke my logic after the first render.

System Info

Any additional comments?

In my experience, a post watcher needs to always have access to the DOM. And sometimes that watcher also needs to run after the first render. Adding immediate: true seems like the logical thing to do in this case, but that breaks the watcher since flush: post will not apply to the "immediate" call. It's difficult to imagine a scenario where the current behavior for this combination would be desirable.

I can think of two workarounds. Both involve nextTick which to me feels kinda hacky compared to watch props.

  1. Instead of flush: 'post', use nextTick() inside the watch callback.
  2. Instead of immediate: true, add nextTick(callback) to the component setup in addition to the watcher.

This issue was also raised in #5023, but it looks like it was closed as "functions as designed" without considering the usefulness of the design.

Maybe it's too late to change the semantics of immediate? I guess my next idea then would be to add an alternate option like initial. But I know growing the API isn't great either.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions