Skip to content

Commit

Permalink
fix(reactivity): triggerRef working with toRef from reactive (#7507)
Browse files Browse the repository at this point in the history
* fix(reactivity): `triggerRef` working with `toRef` from reactive

* chore: refactor
  • Loading branch information
antfu committed Feb 1, 2023
1 parent 5f1883e commit e64c9ae
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 4 deletions.
4 changes: 4 additions & 0 deletions packages/reactivity/src/effect.ts
Expand Up @@ -377,3 +377,7 @@ function triggerEffect(
}
}
}

export function getDepFromReactive(object: any, key: string | number | symbol) {
return targetMap.get(object)?.get(key)
}
12 changes: 9 additions & 3 deletions packages/reactivity/src/ref.ts
@@ -1,5 +1,6 @@
import {
activeEffect,
getDepFromReactive,
shouldTrack,
trackEffects,
triggerEffects
Expand Down Expand Up @@ -53,16 +54,17 @@ export function trackRefValue(ref: RefBase<any>) {

export function triggerRefValue(ref: RefBase<any>, 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)
}
}
}
Expand Down Expand Up @@ -228,6 +230,10 @@ class ObjectRefImpl<T extends object, K extends keyof T> {
set value(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>>
Expand Down
22 changes: 21 additions & 1 deletion packages/runtime-core/__tests__/apiWatch.spec.ts
Expand Up @@ -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
Expand Down Expand Up @@ -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()
Expand Down

0 comments on commit e64c9ae

Please sign in to comment.