Skip to content

Commit 92bf38e

Browse files
chore(overmind-components): more refactoring
1 parent a8a0eaa commit 92bf38e

File tree

22 files changed

+449
-372
lines changed

22 files changed

+449
-372
lines changed

package-lock.json

Lines changed: 8 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
import { EventType } from 'overmind'
2+
import { h } from 'snabbdom/h'
3+
import { VNode, VNodeData } from 'snabbdom/vnode'
4+
5+
import { getApp, getName, patch } from './utils'
6+
7+
const SELF = 'self'
8+
9+
function copyVNode(source: VNode, target: VNode): void {
10+
target.elm = source.elm
11+
12+
target.data = source.data
13+
target.children = source.children
14+
target.text = source.text
15+
target.elm = source.elm
16+
}
17+
18+
let nextId = 0
19+
let nextComponentId = {}
20+
let nextComponentInstanceId = {}
21+
22+
function init(componentVNode: VNode): void {
23+
try {
24+
const component = (componentVNode.data as VNodeData).component
25+
const name = component.name
26+
const tree = component.tree
27+
let currentNode = componentVNode
28+
29+
function createComponentVNode(newState) {
30+
return (component.fn as any)(component.props, {
31+
changeState: update,
32+
state:
33+
typeof newState === 'undefined'
34+
? (currentNode.data as VNodeData).component.state
35+
: newState,
36+
store: tree.state,
37+
actions: getApp().actions,
38+
})
39+
}
40+
41+
function update(newState?) {
42+
tree.track(onFlush)
43+
try {
44+
currentNode.elm = componentVNode.elm
45+
const newNode = createComponentVNode(newState)
46+
newNode.elm = componentVNode.elm
47+
currentNode = patch(currentNode, newNode)
48+
currentNode.elm = componentVNode.elm
49+
} catch (error) {
50+
console.log(name, error.message, currentNode)
51+
}
52+
;(currentNode.data as any).component = (componentVNode.data as any).component
53+
copyVNode(currentNode, componentVNode)
54+
tree.stopTracking()
55+
}
56+
57+
function onFlush(_, __, flushId) {
58+
update()
59+
60+
getApp().eventHub.emitAsync(EventType.COMPONENT_UPDATE, {
61+
componentId: (currentNode.data as any).component.componentId,
62+
componentInstanceId: (currentNode.data as any).component
63+
.componentInstanceId,
64+
name,
65+
flushId,
66+
paths: Array.from(tree.pathDependencies) as any,
67+
})
68+
}
69+
tree.track(onFlush)
70+
currentNode = createComponentVNode(undefined)
71+
;(currentNode.data as any).component = (componentVNode.data as any).component
72+
73+
if (currentNode.sel !== SELF) {
74+
throw new Error(
75+
`You are not returning a <self /> element from the component ${name} `
76+
)
77+
}
78+
tree.stopTracking()
79+
copyVNode(currentNode, componentVNode)
80+
81+
if (!(name in nextComponentId)) {
82+
nextComponentId[name] = nextId++
83+
}
84+
if (!(name in nextComponentInstanceId)) {
85+
nextComponentInstanceId[name] = 0
86+
}
87+
88+
nextComponentInstanceId[name] = nextId++
89+
90+
const componentId = nextComponentId
91+
const componentInstanceId = nextComponentInstanceId[name]
92+
93+
Object.assign(component, {
94+
componentId,
95+
componentInstanceId,
96+
})
97+
98+
getApp().eventHub.emitAsync(EventType.COMPONENT_ADD, {
99+
componentId,
100+
componentInstanceId,
101+
name,
102+
paths: Array.from(tree.pathDependencies) as any,
103+
})
104+
} catch (error) {
105+
console.log(error.message)
106+
}
107+
}
108+
109+
function prepatch(oldVnode: VNode, vnode: VNode): void {
110+
try {
111+
const oldComponent = (oldVnode.data as VNodeData).component
112+
const newComponent = (vnode.data as VNodeData).component
113+
const oldProps = oldComponent.props || {}
114+
const props = newComponent.props || {}
115+
const oldPropsKeys = Object.keys(oldProps)
116+
const propsKeys = Object.keys(props)
117+
const overmind = {
118+
changeState: newComponent.changeState,
119+
state: newComponent.state,
120+
store: newComponent.tree.state,
121+
actions: getApp().actions,
122+
}
123+
124+
if (
125+
oldComponent.fn !== newComponent.fn ||
126+
oldPropsKeys.length !== propsKeys.length
127+
) {
128+
copyVNode((newComponent.fn as any)(props, overmind), vnode)
129+
return
130+
}
131+
132+
const keys = new Set<string>([...oldPropsKeys, ...propsKeys])
133+
134+
for (let key of keys) {
135+
if (oldProps[key] !== props[key]) {
136+
copyVNode((newComponent.fn as any)(props, overmind), vnode)
137+
return
138+
}
139+
}
140+
141+
copyVNode(oldVnode, vnode)
142+
} catch (error) {
143+
console.log(error.message)
144+
}
145+
}
146+
147+
function postpatch(prevNode, nextNode) {
148+
try {
149+
nextNode.data.component = prevNode.data.component
150+
} catch (error) {
151+
console.log(error.message)
152+
}
153+
}
154+
155+
function destroy(node) {
156+
try {
157+
getApp().disposeTree(node.data.component.tree)
158+
} catch (error) {
159+
console.log(error.message)
160+
}
161+
}
162+
163+
export const component = (component, props, children) => {
164+
const name = getName(component.name)
165+
166+
return h(name, {
167+
key: props ? props.key : undefined,
168+
hook: {
169+
init,
170+
prepatch,
171+
postpatch,
172+
destroy,
173+
},
174+
component: {
175+
fn: component,
176+
name,
177+
state: undefined,
178+
changeState: null,
179+
props: {
180+
...props,
181+
children: children.length ? children : null,
182+
},
183+
tree: getApp().proxyStateTree.getTrackStateTree(),
184+
},
185+
})
186+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { VALUE } from 'proxy-state-tree'
2+
import h from 'snabbdom/h'
3+
4+
import { component } from './component'
5+
import { SELF, getName, normalizeAttrs } from './utils'
6+
7+
export const createElement = (tag, attrs, ...children) => {
8+
if (typeof tag === 'function') {
9+
return component(tag, attrs, children)
10+
}
11+
12+
return h(
13+
tag,
14+
normalizeAttrs(tag, attrs),
15+
children.reduce((aggr, item) => aggr.concat(item), [])
16+
)
17+
}

0 commit comments

Comments
 (0)