Skip to content

Commit e395540

Browse files
committed
improve dot notation
1 parent 0145962 commit e395540

File tree

3 files changed

+31
-22
lines changed

3 files changed

+31
-22
lines changed

observableStateTree/dotNotation.tsx

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,16 @@ import { createDotNotationProxy } from './dotNotationProxy'
33

44
export const createStore = (initial: any) => {
55
const { get, set, listen } = createStateTree(initial)
6-
const specialKeys = new Set(['val', 'listen'])
7-
const onGet = (key: string, path: string[]) => {
8-
if (key === 'val') return get(path)
9-
if (key === 'listen') return (callback: Callback) => listen(path, callback)
6+
const listenKey = Symbol()
7+
const valKey = Symbol()
8+
const specialKeys = new Set([valKey, listenKey])
9+
const onGet = (key: symbol, path: string[]) => {
10+
if (key === valKey) return get(path)
11+
if (key === listenKey) return (callback: Callback) => listen(path, callback)
12+
}
13+
return {
14+
tree: createDotNotationProxy(onGet, set, specialKeys) as any,
15+
listen: (node: any, callback: Callback) => node[listenKey](callback),
16+
val: (node: any) => node[valKey],
1017
}
11-
return createDotNotationProxy(onGet, set, specialKeys) as any
1218
}

observableStateTree/dotNotationProxy.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,25 @@
11
export const createDotNotationProxy = (
2-
onGet: (key: string, path: string[]) => unknown,
2+
onGet: (key: symbol, path: string[]) => unknown,
33
onSet: (path: string[], value: unknown) => void,
4-
specialKeys: Set<string>,
4+
specialKeys: Set<symbol>,
55
path: string[] = []
66
): typeof Proxy => {
77
return new Proxy(
88
{},
99
{
10-
get: (target, key: string) => {
10+
get: (target, key: string | symbol) => {
11+
if (typeof key === 'string') {
12+
return createDotNotationProxy(onGet, onSet, specialKeys, [...path, key])
13+
}
1114
if (specialKeys.has(key)) return onGet(key, path)
12-
return createDotNotationProxy(onGet, onSet, specialKeys, [...path, key])
15+
throw new Error('symbol keys are not supported')
1316
},
14-
set: (target: any, key: string, value: unknown) => {
15-
if (specialKeys.has(key)) {
16-
throw new Error(`sorry you may not use "${key}" as a key`)
17+
set: (target: any, key: string | symbol, value: unknown) => {
18+
if (typeof key === 'string') {
19+
onSet([...path, key], value)
20+
return true
1721
}
18-
onSet([...path, key], value)
19-
return true
22+
throw new Error('symbol keys are not supported')
2023
},
2124
}
2225
)

pages/dotNotationExample.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,21 @@ import { createStore } from '../observableStateTree/dotNotation'
33

44
const test = () => {
55
console.clear()
6-
const tree = createStore({ a: { b: { c: 1, d: 1 } } })
6+
const { tree, listen, val } = createStore({ a: { b: { c: 1, d: 1 } } })
77
// the tree behaves like a normal object e.g
8-
console.log('tree', tree.val)
8+
console.log('tree', val(tree))
99
// prints the object 👉 { a: { b: { c : 1, d: 1 } } }
1010

1111
// we can setup listeners
12-
const destroyRoot = tree.listen((root: any) => console.log('root', root))
12+
const destroyRoot = listen(tree, (root: any) => console.log('root', root))
1313
// on initial setup prints the full tree 👉 root { a: { b: { c: 1, d: 1 } } }
14-
const destroyA = tree.a.listen((a: any) => console.log('a', a))
14+
const destroyA = listen(tree.a, (a: any) => console.log('a', a))
1515
// 👉 a { b: { c: 1 } }
16-
const destroyB = tree.a.b.listen((b: any) => console.log('b', b))
16+
const destroyB = listen(tree.a.b, (b: any) => console.log('b', b))
1717
// 👉 b { c: 1 }
18-
const destroyC = tree.a.b.c.listen((c: any) => console.log('c', c))
18+
const destroyC = listen(tree.a.b.c, (c: any) => console.log('c', c))
1919
// 👉 c 1
20-
const destroyD = tree.a.b.c.listen((d: any) => console.log('d', d))
20+
const destroyD = listen(tree.a.b.c, (d: any) => console.log('d', d))
2121
// 👉 d 1
2222

2323
// should also support sending the prev value
@@ -36,7 +36,7 @@ const test = () => {
3636

3737
// 🙋‍♂️
3838
// 2. Modifying a parent notifies the relevant children listeners.
39-
tree.a = { ...tree.a.val }
39+
tree.a = { ...val(tree.a) }
4040
// 👉 a { b: { c: 2 } }
4141
// a is fired but b, c and d are not fired
4242
tree.a = { e: 1 }

0 commit comments

Comments
 (0)