From e64c9ae957aa2606b55e8652bbde30a6ada59fb0 Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Wed, 1 Feb 2023 09:20:47 +0100 Subject: [PATCH] fix(reactivity): `triggerRef` working with `toRef` from reactive (#7507) * fix(reactivity): `triggerRef` working with `toRef` from reactive * chore: refactor --- packages/reactivity/src/effect.ts | 4 ++++ packages/reactivity/src/ref.ts | 12 +++++++--- .../runtime-core/__tests__/apiWatch.spec.ts | 22 ++++++++++++++++++- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/packages/reactivity/src/effect.ts b/packages/reactivity/src/effect.ts index 9ef38c1b065..5eb84bc48d7 100644 --- a/packages/reactivity/src/effect.ts +++ b/packages/reactivity/src/effect.ts @@ -377,3 +377,7 @@ function triggerEffect( } } } + +export function getDepFromReactive(object: any, key: string | number | symbol) { + return targetMap.get(object)?.get(key) +} diff --git a/packages/reactivity/src/ref.ts b/packages/reactivity/src/ref.ts index 26c6fe192ba..124e2aaa869 100644 --- a/packages/reactivity/src/ref.ts +++ b/packages/reactivity/src/ref.ts @@ -1,5 +1,6 @@ import { activeEffect, + getDepFromReactive, shouldTrack, trackEffects, triggerEffects @@ -53,16 +54,17 @@ export function trackRefValue(ref: RefBase) { export function triggerRefValue(ref: RefBase, newVal?: any) { ref = toRaw(ref) - if (ref.dep) { + const dep = ref.dep + if (dep) { if (__DEV__) { - triggerEffects(ref.dep, { + triggerEffects(dep, { target: ref, type: TriggerOpTypes.SET, key: 'value', newValue: newVal }) } else { - triggerEffects(ref.dep) + triggerEffects(dep) } } } @@ -228,6 +230,10 @@ class ObjectRefImpl { set value(newVal) { this._object[this._key] = newVal } + + get dep(): Dep | undefined { + return getDepFromReactive(toRaw(this._object), this._key) + } } export type ToRef = IfAny, [T] extends [Ref] ? T : Ref> diff --git a/packages/runtime-core/__tests__/apiWatch.spec.ts b/packages/runtime-core/__tests__/apiWatch.spec.ts index b9670820cd9..73fe02cc8fa 100644 --- a/packages/runtime-core/__tests__/apiWatch.spec.ts +++ b/packages/runtime-core/__tests__/apiWatch.spec.ts @@ -30,7 +30,8 @@ import { triggerRef, shallowRef, Ref, - effectScope + effectScope, + toRef } from '@vue/reactivity' // reference: https://vue-composition-api-rfc.netlify.com/api.html#watch @@ -926,6 +927,25 @@ describe('api: watch', () => { expect(spy).toHaveBeenCalledTimes(1) }) + test('should force trigger on triggerRef with toRef from reactive', async () => { + const foo = reactive({ bar: 1 }) + const bar = toRef(foo, 'bar') + const spy = jest.fn() + + watchEffect(() => { + bar.value + spy() + }) + + expect(spy).toHaveBeenCalledTimes(1) + + triggerRef(bar) + + await nextTick() + // should trigger now + expect(spy).toHaveBeenCalledTimes(2) + }) + // #2125 test('watchEffect should not recursively trigger itself', async () => { const spy = vi.fn()