Repository: vuejs/composition-api
Pull request #727 (2021-06-08 07:26:09)

fix(watch): watched previous values can't be destructure on first fire.
Fix: #418, align behavior with vue-next.



Patch:
diff --git a/src/apis/watch.ts b/src/apis/watch.ts
index 3f61414..c3cb5a8 100644
--- a/src/apis/watch.ts
+++ b/src/apis/watch.ts
@@ -329,7 +329,8 @@ function createWatcher(
     // The subsequent callbacks will redirect to `callback`.
     let shiftCallback = (n: any, o: any) => {
       shiftCallback = originalCallback
-      applyCb(n, o)
+      // o is undefined on the first call
+      applyCb(n, isArray(n) ? [] : o)
     }
     callback = (n: any, o: any) => {
       shiftCallback(n, o)
diff --git a/src/reactivity/ref.ts b/src/reactivity/ref.ts
index ce8458a..32c187d 100644
--- a/src/reactivity/ref.ts
+++ b/src/reactivity/ref.ts
@@ -198,16 +198,16 @@ export function proxyRefs<T extends object>(
   for (const key of Object.keys(objectWithRefs)) {
     proxy(value, key, {
       get() {
-        if (isRef(value[key])) {
-          return value[key].value
+        if (isRef(value[RefKey][key])) {
+          return value[RefKey][key].value
         }
-        return value[key]
+        return value[RefKey][key]
       },
       set(v: unknown) {
-        if (isRef(value[key])) {
-          return (value[key].value = unref(v))
+        if (isRef(value[RefKey][key])) {
+          return (value[RefKey][key].value = unref(v))
         }
-        value[key] = unref(v)
+        value[RefKey][key] = unref(v)
       },
     })
   }


Test patch:
diff --git a/test/apis/watch.spec.js b/test/apis/watch.spec.js
index 33f5b62..eeb323e 100644
--- a/test/apis/watch.spec.js
+++ b/test/apis/watch.spec.js
@@ -457,7 +457,7 @@ describe('api/watch', () => {
         template: `<div>{{obj1.a}} {{obj2.a}}</div>`,
       }).$mount()
       expect(spy).toBeCalledTimes(1)
-      expect(spy).toHaveBeenLastCalledWith([1, 2], undefined)
+      expect(spy).toHaveBeenLastCalledWith([1, 2], [])
       obj1.a = 2
       obj2.a = 3
 
@@ -491,7 +491,7 @@ describe('api/watch', () => {
         template: `<div>{{a}} {{b}}</div>`,
       }).$mount()
       expect(spy).toBeCalledTimes(1)
-      expect(spy).toHaveBeenLastCalledWith([1, 1], undefined)
+      expect(spy).toHaveBeenLastCalledWith([1, 1], [])
       vm.a = 2
       expect(spy).toBeCalledTimes(1)
       waitForUpdate(() => {
@@ -553,7 +553,7 @@ describe('api/watch', () => {
         },
       })
       expect(spy).toBeCalledTimes(1)
-      expect(spy).toHaveBeenLastCalledWith([1, 1], undefined)
+      expect(spy).toHaveBeenLastCalledWith([1, 1], [])
       vm.a = 2
       expect(spy).toBeCalledTimes(2)
       expect(spy).toHaveBeenLastCalledWith([2, 1], [1, 1])
diff --git a/test/v3/reactivity/ref.spec.ts b/test/v3/reactivity/ref.spec.ts
index 6806224..26f8078 100644
--- a/test/v3/reactivity/ref.spec.ts
+++ b/test/v3/reactivity/ref.spec.ts
@@ -12,6 +12,7 @@ import {
   unref,
   isReactive,
   shallowRef,
+  proxyRefs,
 } from '../../../src'
 
 describe('reactivity/ref', () => {
@@ -342,4 +343,29 @@ describe('reactivity/ref', () => {
     _trigger!()
     expect(dummy).toBe(2)
   })
+
+  test('proxyRefs', () => {
+    const a = {
+      x: ref(1),
+      obj: {
+        y: ref('foo'),
+      },
+    }
+    const p = proxyRefs(a)
+    expect(p.x).toBe(1)
+    expect(p.obj.y).toBe('foo')
+
+    // @ts-expect-error
+    p.obj.y = 'bar'
+    p.x = 2
+    expect(a.x).toBe(2)
+    expect(a.obj.y).toBe('bar')
+
+    const r = reactive({ k: 'v' })
+    const s = proxyRefs(r)
+    expect(s.k).toBe('v')
+
+    r.k = 'k'
+    expect(s.k).toBe('k')
+  })
 })