Repository: pmndrs/valtio
Pull request #23 (2020-11-22 04:46:50)

skip setting property if not changed
https://github.com/pmndrs/valtio/issues/20#issuecomment-731644189

The fix is rather simple.

@wilcoschoneveld How does it look?

codesandbox[bot]: This pull request is automatically built and testable in [CodeSandbox](https://codesandbox.io).

  To see build info of the built libraries, click [here](https://ci.codesandbox.io/status/pmndrs/valtio/pr/23/builds/75718) or the icon next to each commit SHA.

Latest deployment of this branch, based on commit a56dc6e2d4c958029b92b634127f10bd85a40abb:

|Sandbox| Source |
|--|--|
|[React](https://codesandbox.io/s/react-1kq3c)| Configuration |
|[React Typescript](https://codesandbox.io/s/react-typescript-grmnk)| Configuration |


Patch:
diff --git a/.size-snapshot.json b/.size-snapshot.json
index 4909507..29dcc86 100644
--- a/.size-snapshot.json
+++ b/.size-snapshot.json
@@ -1,8 +1,8 @@
 {
   "index.js": {
-    "bundled": 5443,
-    "minified": 2395,
-    "gzipped": 1028,
+    "bundled": 5558,
+    "minified": 2455,
+    "gzipped": 1049,
     "treeshaked": {
       "rollup": {
         "code": 61,
@@ -14,19 +14,19 @@
     }
   },
   "index.cjs.js": {
-    "bundled": 6167,
-    "minified": 2826,
-    "gzipped": 1127
+    "bundled": 6288,
+    "minified": 2881,
+    "gzipped": 1153
   },
   "index.iife.js": {
-    "bundled": 6555,
-    "minified": 2153,
-    "gzipped": 994
+    "bundled": 6688,
+    "minified": 2208,
+    "gzipped": 1011
   },
   "vanilla.js": {
-    "bundled": 3670,
-    "minified": 1586,
-    "gzipped": 747,
+    "bundled": 3785,
+    "minified": 1646,
+    "gzipped": 763,
     "treeshaked": {
       "rollup": {
         "code": 22,
@@ -38,8 +38,8 @@
     }
   },
   "vanilla.cjs.js": {
-    "bundled": 4144,
-    "minified": 1881,
-    "gzipped": 830
+    "bundled": 4265,
+    "minified": 1936,
+    "gzipped": 853
   }
 }
diff --git a/src/vanilla.ts b/src/vanilla.ts
index 798b9c6..5995c85 100644
--- a/src/vanilla.ts
+++ b/src/vanilla.ts
@@ -19,20 +19,14 @@ const snapshotCache = new WeakMap<
 
 export const proxy = <T extends object>(initialObject: T = {} as T): T => {
   let version = globalVersion
-  let pendingVersion = version
-  const listeners = new Set<(nextVersion?: number) => void>()
+  const listeners = new Set<(nextVersion: number) => void>()
   const notifyUpdate = (nextVersion?: number) => {
     if (!nextVersion) {
       nextVersion = ++globalVersion
     }
-    if (nextVersion > pendingVersion) {
-      pendingVersion = nextVersion
-      Promise.resolve().then(() => {
-        if (pendingVersion > version) {
-          version = pendingVersion
-          listeners.forEach((listener) => listener(version))
-        }
-      })
+    if (version !== nextVersion) {
+      version = nextVersion
+      listeners.forEach((listener) => listener(nextVersion as number))
     }
   }
   const emptyCopy = Array.isArray(initialObject)
@@ -88,6 +82,9 @@ export const proxy = <T extends object>(initialObject: T = {} as T): T => {
       return true
     },
     set(target, prop, value, receiver) {
+      if (Object.is(target[prop], value)) {
+        return true
+      }
       const childListeners = isObject(target[prop]) && target[prop][LISTENERS]
       if (childListeners) {
         childListeners.delete(notifyUpdate)
@@ -123,9 +120,18 @@ export const proxy = <T extends object>(initialObject: T = {} as T): T => {
 export const getVersion = (p: any): number => p[VERSION]
 
 export const subscribe = (p: any, callback: () => void) => {
-  p[LISTENERS].add(callback)
+  let pendingVersion = 0
+  const listener = (nextVersion: number) => {
+    pendingVersion = nextVersion
+    Promise.resolve().then(() => {
+      if (nextVersion === pendingVersion) {
+        callback()
+      }
+    })
+  }
+  p[LISTENERS].add(listener)
   return () => {
-    p[LISTENERS].delete(callback)
+    p[LISTENERS].delete(listener)
   }
 }
 


Test patch:
diff --git a/tests/subscribe.test.tsx b/tests/subscribe.test.tsx
index 04c0894..6048120 100644
--- a/tests/subscribe.test.tsx
+++ b/tests/subscribe.test.tsx
@@ -45,7 +45,7 @@ describe('subscribe', () => {
     expect(() => subscribe(obj.count, handler)).toThrow()
   })
 
-  it.skip('should not re-run subscription if no change', async () => {
+  it('should not re-run subscription if no change', async () => {
     const obj = proxy({ count: 0 })
     const handler = jest.fn()