Skip to content

Commit 4ebdb2b

Browse files
authored
feat: ref api (#62)
* feat: ref api * fix: ref * update readme * fix readme
1 parent eb32d41 commit 4ebdb2b

File tree

3 files changed

+35
-10
lines changed

3 files changed

+35
-10
lines changed

readme.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
<img src="logo.svg">
1+
<img src="logo.svg" alt="valtio">
2+
<br />
23
<br />
3-
<br/>
44

55
<code>npm i valtio</code> makes proxy-state simple
66

@@ -107,6 +107,20 @@ You can subscribe a component to state without causing render, just stick the su
107107
function Foo() {
108108
const ref = useRef(state.obj)
109109
useEffect(() => subscribe(state.obj, () => ref.current = state.obj), [state.obj])
110+
// ...
111+
```
112+
113+
##### Avoid state properties to be wrapped with proxies
114+
115+
See https://github.com/pmndrs/valtio/pull/62 for more information.
116+
117+
```js
118+
import { proxy, ref } from 'valtio'
119+
120+
const state = proxy({
121+
count: 0,
122+
dom: ref(document.body),
123+
})
110124
```
111125
112126
##### Dev tools

src/index.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,14 @@ import {
1414
} from 'proxy-compare'
1515

1616
import { createMutableSource, useMutableSource } from './useMutableSource'
17-
import { proxy, getVersion, subscribe, snapshot, NonPromise } from './vanilla'
17+
import {
18+
proxy,
19+
getVersion,
20+
subscribe,
21+
snapshot,
22+
ref,
23+
NonPromise,
24+
} from './vanilla'
1825

1926
const isSSR =
2027
typeof window === 'undefined' ||
@@ -110,4 +117,4 @@ const useProxy = <T extends object>(p: T, options?: Options): NonPromise<T> => {
110117
return createDeepProxy(currSnapshot, affected, proxyCache)
111118
}
112119

113-
export { proxy, subscribe, snapshot, useProxy }
120+
export { proxy, subscribe, snapshot, ref, useProxy }

src/vanilla.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ const SNAPSHOT = Symbol()
66
const PROMISE_RESULT = Symbol()
77
const PROMISE_ERROR = Symbol()
88

9+
const refSet = new WeakSet()
10+
export const ref = (o: object) => {
11+
refSet.add(o)
12+
return o
13+
}
14+
915
const isSupportedObject = (x: unknown): x is object =>
1016
typeof x === 'object' &&
1117
x !== null &&
@@ -72,7 +78,7 @@ export const proxy = <T extends object>(initialObject: T = {} as T): T => {
7278
snapshotCache.set(receiver, { version, snapshot })
7379
Reflect.ownKeys(target).forEach((key) => {
7480
const value = target[key]
75-
if (!isSupportedObject(value)) {
81+
if (refSet.has(value) || !isSupportedObject(value)) {
7682
snapshot[key] = value
7783
} else if (value instanceof Promise) {
7884
if (PROMISE_RESULT in (value as any)) {
@@ -103,8 +109,7 @@ export const proxy = <T extends object>(initialObject: T = {} as T): T => {
103109
},
104110
deleteProperty(target, prop) {
105111
const prevValue = target[prop]
106-
const childListeners =
107-
isSupportedObject(prevValue) && (prevValue as any)[LISTENERS]
112+
const childListeners = prevValue && (prevValue as any)[LISTENERS]
108113
if (childListeners) {
109114
childListeners.delete(notifyUpdate)
110115
}
@@ -119,12 +124,11 @@ export const proxy = <T extends object>(initialObject: T = {} as T): T => {
119124
if (Object.is(prevValue, value)) {
120125
return true
121126
}
122-
const childListeners =
123-
isSupportedObject(prevValue) && (prevValue as any)[LISTENERS]
127+
const childListeners = prevValue && (prevValue as any)[LISTENERS]
124128
if (childListeners) {
125129
childListeners.delete(notifyUpdate)
126130
}
127-
if (!isSupportedObject(value)) {
131+
if (refSet.has(value) || !isSupportedObject(value)) {
128132
target[prop] = value
129133
} else if (value instanceof Promise) {
130134
target[prop] = value

0 commit comments

Comments
 (0)