Export `trigger` from `@vue/reactive` in browser bundles.
What problem does this feature solve?
We have a few edge cases in our Vue 3 library (FormKit) where it would be useful to manually trigger the dependencies of a reactive
property. This typically this happens during compute-heavy operations dealing with deeply nested objects and its important not to trigger any deps until a specific "time". The use cases are effectively the same as triggerRef
but for properties of a reactive
object (in a library where users can pass either reactive
or ref
).
Our hope is to do this by getting the reactive
proxy target (via toRaw
) running the expensive process, and then triggering the specific properties that were updated at a (slightly) later time. This can be done already using trigger
from @vue/reactive
— however since the browser bundle does not export trigger we cannot use this for users who want CDN support, even with an import map since the module scopes are different.
What does the proposed API look like?
Ultimately it would be great to be able to do:
import { trigger } from 'vue'
Where vue is any of the bundled versions.
@posva I think it is only possible if we control the type of object passed to us. In our scenario, we expect users to be able to pass in a ref
or a reactive
without discrimination — and in this scenario I don't think customRef
is enough (I would love to be proved wrong).
From reading the Vue reactivity source code my hunch is that deps of a reactive property are not copied to the ref.dep
property during a toRef
and triggerRefValue
only operates on the effects in ref.dep
.
Here's a minimal reproduction in the Vue SFC playground:
- Setup (no attempt): http://brd.bz/419ab131
- Attempt: triggerRef: http://brd.bz/abe62adc
- Attempt: customRef: http://brd.bz/8b751809
I suppose it would be possible, in theory to proxy the reactive object itself, not apply any changes to the object itself, but to some temporary facsimile, and then explicitly assign those values to the reactive object during a "trigger" event meaning the original reactive object would have direct assignments and its deps would be triggered but this would be a lot of unnecessary code and the underlying object that is being operated on would not be the same, so a WeakMap
or a WeakSet
could not track it properly.
A solution to all this would be some way to manually trigger the deps of a reactive object like triggerReactive
.
Can't you set one of the reactive properties only like so
Thats interesting @posva — I suppose that works because the flush timing on those updates causes only 1 mutation to be made (wouldn't want multiple triggers).
Unfortunately — im not sure it works in our specific use case where v-model comes into play since the emits
does not squash any events. A more fleshed out example where v-model is at play:
- With v-model: http://brd.bz/7e1f4e7d
- With spreading:: http://brd.bz/59a550ab — of course this works with spreading the objects, but we'd love to avoid this as any code using referencing these objects with Map/Set/WeakMap/WeakSet will be broken.
- With re-assignment (like in your last example): http://brd.bz/60f3c932 — this seems pretty hacky, and unfortunately it still doesn't work
If we could emit the update:modelValue
and explicitly trigger deps we'd be in a good place perhaps, but I think we still need some kind of access to trigger
— again would love to be wrong