fix(reactivity): `triggerRef` working with `toRef` from reactive (#7507)

* fix(reactivity): `triggerRef` working with `toRef` from reactive

* chore: refactor
This commit is contained in:
Anthony Fu 2023-02-01 09:20:47 +01:00 committed by GitHub
parent 5f1883ec53
commit e64c9ae957
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 4 deletions

View File

@ -377,3 +377,7 @@ function triggerEffect(
} }
} }
} }
export function getDepFromReactive(object: any, key: string | number | symbol) {
return targetMap.get(object)?.get(key)
}

View File

@ -1,5 +1,6 @@
import { import {
activeEffect, activeEffect,
getDepFromReactive,
shouldTrack, shouldTrack,
trackEffects, trackEffects,
triggerEffects triggerEffects
@ -53,16 +54,17 @@ export function trackRefValue(ref: RefBase<any>) {
export function triggerRefValue(ref: RefBase<any>, newVal?: any) { export function triggerRefValue(ref: RefBase<any>, newVal?: any) {
ref = toRaw(ref) ref = toRaw(ref)
if (ref.dep) { const dep = ref.dep
if (dep) {
if (__DEV__) { if (__DEV__) {
triggerEffects(ref.dep, { triggerEffects(dep, {
target: ref, target: ref,
type: TriggerOpTypes.SET, type: TriggerOpTypes.SET,
key: 'value', key: 'value',
newValue: newVal newValue: newVal
}) })
} else { } else {
triggerEffects(ref.dep) triggerEffects(dep)
} }
} }
} }
@ -228,6 +230,10 @@ class ObjectRefImpl<T extends object, K extends keyof T> {
set value(newVal) { set value(newVal) {
this._object[this._key] = newVal this._object[this._key] = newVal
} }
get dep(): Dep | undefined {
return getDepFromReactive(toRaw(this._object), this._key)
}
} }
export type ToRef<T> = IfAny<T, Ref<T>, [T] extends [Ref] ? T : Ref<T>> export type ToRef<T> = IfAny<T, Ref<T>, [T] extends [Ref] ? T : Ref<T>>

View File

@ -30,7 +30,8 @@ import {
triggerRef, triggerRef,
shallowRef, shallowRef,
Ref, Ref,
effectScope effectScope,
toRef
} from '@vue/reactivity' } from '@vue/reactivity'
// reference: https://vue-composition-api-rfc.netlify.com/api.html#watch // reference: https://vue-composition-api-rfc.netlify.com/api.html#watch
@ -926,6 +927,25 @@ describe('api: watch', () => {
expect(spy).toHaveBeenCalledTimes(1) 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 // #2125
test('watchEffect should not recursively trigger itself', async () => { test('watchEffect should not recursively trigger itself', async () => {
const spy = vi.fn() const spy = vi.fn()