Skip to content

Commit 0c0cd61

Browse files
Merge pull request cerebral#165 from cerebral/fixes3
Fixes3
2 parents 0e2b32d + a0c036b commit 0c0cd61

File tree

59 files changed

+3048
-1238
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+3048
-1238
lines changed

packages/node_modules/overmind-angular/src/index.ts

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,6 @@ export type TConnect<Config extends Configuration> = {
77
overmind: {
88
state: TApp<Config>['state']
99
actions: TApp<Config>['actions']
10-
reaction: (
11-
name: string,
12-
stateCb: (state: TApp<Config>['state']) => any,
13-
Function
14-
) => void
1510
}
1611
}
1712

@@ -27,15 +22,11 @@ export const createConnect = <A extends Overmind<any>>(overmind: A) => () => {
2722
const targetNgAfterContentInit = target.prototype.ngAfterContentInit
2823
const targetNgAfterViewInit = target.prototype.ngAfterViewInit
2924
const targetNgAfterViewChecked = target.prototype.ngAfterViewChecked
30-
const reactionFactory = overmind.createReactionFactory(
31-
target.constructor.name
32-
)
3325

3426
target.prototype.ngOnInit = function() {
3527
this.overmind = {
3628
state: overmind.state,
3729
actions: overmind.actions,
38-
reaction: reactionFactory.add,
3930
}
4031
this.__componentInstanceId = componentInstanceId++
4132
this.__shouldUpdatePaths = false
@@ -75,7 +66,7 @@ export const createConnect = <A extends Overmind<any>>(overmind: A) => () => {
7566
name: this.constructor.name || '',
7667
paths: Array.from(paths),
7768
})
78-
this.__listener = overmind.addMutationListener(paths, (flushId) => {
69+
this.__listener = overmind.addFlushListener(paths, (flushId) => {
7970
this.__shouldUpdatePaths = true
8071
if (this.cdr) {
8172
this.cdr.markForCheck()
@@ -133,7 +124,6 @@ export const createConnect = <A extends Overmind<any>>(overmind: A) => () => {
133124
name: this.constructor.name || '',
134125
})
135126
this.__listener.dispose()
136-
this.__reactionFactory.dispose()
137127
}
138128

139129
return target
Lines changed: 126 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -1,138 +1,149 @@
11
import { Overmind } from 'overmind'
2-
import { testRender } from './testRender'
3-
import { Component, h, useOvermind } from './'
2+
import { mockDocument } from './mockDocument'
3+
import { Component, h, useOvermind, render } from './'
44
import { Null } from './Null'
55

66
describe('COMPONENT', () => {
77
test('should reconcile components', () => {
8-
const app = new Overmind({})
9-
const TestCompA = () => <div>foo</div>
10-
const TestCompB = () => <div>bar</div>
11-
const test = testRender(
12-
app,
13-
<div>
14-
<TestCompA />
15-
</div>
16-
)
17-
const target = test.getTargetElement()
18-
19-
target.children[0].reconcile(
20-
<div>
21-
<TestCompB />
22-
</div>
23-
)
24-
25-
expect(test.getUpdates().length).toBe(10)
26-
expect(target.children[0].children[0].vtree.children[0].el.nodeValue).toBe(
27-
'bar'
28-
)
8+
mockDocument((target, updates) => {
9+
const app = new Overmind({})
10+
const TestCompA = () => <div id="foo">foo</div>
11+
const TestCompB = () => <div id="bar">bar</div>
12+
const parent = render(
13+
app,
14+
<div id="parent">
15+
<TestCompA />
16+
</div>,
17+
target
18+
)
19+
20+
parent.children[0].reconcile(
21+
<div>
22+
<TestCompB />
23+
</div>
24+
)
25+
26+
expect(updates).toMatchSnapshot()
27+
expect(target.innerHTML).toMatchSnapshot()
28+
})
2929
})
30+
3031
test('should reconcile NULL components to component', () => {
31-
const app = new Overmind({})
32-
const TestCompA = () => null
33-
const TestCompB = () => <div>bar</div>
34-
const test = testRender(
35-
app,
36-
<div>
37-
<TestCompA />
38-
</div>
39-
)
40-
const target = test.getTargetElement()
41-
42-
target.children[0].reconcile(
43-
<div>
44-
<TestCompB />
45-
</div>
46-
)
47-
48-
expect(test.getUpdates().length).toBe(6)
49-
expect(target.children[0].children[0].vtree.children[0].el.nodeValue).toBe(
50-
'bar'
51-
)
32+
mockDocument((target, updates) => {
33+
const app = new Overmind({})
34+
const TestCompA = () => null
35+
const TestCompB = () => <div id="bar">bar</div>
36+
const parent = render(
37+
app,
38+
<div id="parent">
39+
<TestCompA />
40+
</div>,
41+
target
42+
)
43+
44+
parent.children[0].reconcile(
45+
<div id="parent">
46+
<TestCompB />
47+
</div>
48+
)
49+
50+
expect(updates).toMatchSnapshot()
51+
expect(target.innerHTML).toMatchSnapshot()
52+
})
5253
})
54+
5355
test('should reconcile components to NULL component', () => {
54-
const app = new Overmind({})
55-
const TestCompA = () => <div>foo</div>
56-
const TestCompB = () => null
57-
const test = testRender(
58-
app,
59-
<div>
60-
<TestCompA />
61-
</div>
62-
)
63-
const target = test.getTargetElement()
64-
65-
target.children[0].reconcile(
66-
<div>
67-
<TestCompB />
68-
</div>
69-
)
70-
71-
expect(test.getUpdates().length).toBe(7)
72-
73-
expect(target.children[0].children[0].vtree).toBeInstanceOf(Null)
56+
mockDocument((target, updates) => {
57+
const app = new Overmind({})
58+
const TestCompA = () => <div id="foo">foo</div>
59+
const TestCompB = () => null
60+
const parent = render(
61+
app,
62+
<div id="parent">
63+
<TestCompA />
64+
</div>,
65+
target
66+
)
67+
68+
parent.children[0].reconcile(
69+
<div id="parent">
70+
<TestCompB />
71+
</div>
72+
)
73+
74+
expect(updates).toMatchSnapshot()
75+
expect(target.innerHTML).toMatchSnapshot()
76+
})
7477
})
78+
7579
test('should reconcile NULL components to NULL component', () => {
76-
const app = new Overmind({})
77-
const TestCompA = () => null
78-
const TestCompB = () => null
79-
const test = testRender(
80-
app,
81-
<div>
82-
<TestCompA />
83-
</div>
84-
)
85-
const target = test.getTargetElement()
86-
87-
target.children[0].reconcile(
88-
<div>
89-
<TestCompB />
90-
</div>
91-
)
92-
93-
expect(test.getUpdates().length).toBe(2)
94-
95-
expect(target.children[0].children[0].vtree).toBeInstanceOf(Null)
80+
mockDocument((target, updates) => {
81+
const app = new Overmind({})
82+
const TestCompA = () => null
83+
const TestCompB = () => null
84+
const parent = render(
85+
app,
86+
<div id="parent">
87+
<TestCompA />
88+
</div>,
89+
target
90+
)
91+
92+
parent.children[0].reconcile(
93+
<div id="parent">
94+
<TestCompB />
95+
</div>
96+
)
97+
98+
expect(updates).toMatchSnapshot()
99+
100+
expect(target.innerHTML).toMatchSnapshot()
101+
})
96102
})
103+
97104
test('should reconcile nested components from within', () => {
98-
const app = new Overmind({})
99-
let renderCount = 0
100-
const TestCompA = () => (renderCount++ ? <span>foo</span> : <div>bar</div>)
101-
const TestCompB = () => <TestCompA />
102-
const test = testRender(app, <TestCompB />)
103-
const target = test.getTargetElement()
104-
const testCompA = target.children[0].vtree
105-
106-
testCompA.reconcile(testCompA, true)
107-
108-
expect(test.getUpdates().length).toBe(8)
109-
expect(target.children[0].vtree.vtree.children[0].el.nodeValue).toBe('foo')
105+
mockDocument((target, updates) => {
106+
const app = new Overmind({})
107+
let renderCount = 0
108+
const TestCompA = () =>
109+
renderCount++ ? <span id="foo">foo</span> : <div id="bar">bar</div>
110+
const TestCompB = () => <TestCompA />
111+
const parent = render(app, <TestCompB />, target)
112+
const testCompA = parent.children[0].vtree
113+
114+
testCompA.reconcile(testCompA, true)
115+
116+
expect(updates).toMatchSnapshot()
117+
expect(target.innerHTML).toMatchSnapshot()
118+
})
110119
})
120+
111121
test('should update on state changes', () => {
112-
const config = {
113-
state: {
114-
foo: true,
115-
},
116-
actions: {
117-
changeFoo({ state }) {
118-
state.foo = false
122+
mockDocument((target, updates) => {
123+
const config = {
124+
state: {
125+
foo: true,
126+
},
127+
actions: {
128+
changeFoo({ state }) {
129+
state.foo = false
130+
},
119131
},
120-
},
121-
}
122-
const app = new Overmind(config)
132+
}
133+
const app = new Overmind(config)
123134

124-
const TestComp: Component = () => {
125-
const { state } = useOvermind<typeof config>()
126-
return state.foo ? <span>foo</span> : <div>bar</div>
127-
}
135+
const TestComp: Component = () => {
136+
const { state } = useOvermind<typeof config>()
137+
return state.foo ? <span>foo</span> : <div>bar</div>
138+
}
128139

129-
const test = testRender(app, <TestComp />)
130-
const target = test.getTargetElement()
140+
render(app, <TestComp />, target)
131141

132-
app.actions.changeFoo()
142+
app.actions.changeFoo()
133143

134-
expect(test.getUpdates().length).toBe(8)
144+
expect(updates).toMatchSnapshot()
135145

136-
expect(target.children[0].vtree.children[0].el.nodeValue).toBe('bar')
146+
expect(target.innerHTML).toMatchSnapshot()
147+
})
137148
})
138149
})

packages/node_modules/overmind-components/src/Component.ts

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export class Component {
3636
vtree: any
3737
isReconciling: any
3838
asyncRender: any
39+
isMounted: boolean = false
3940
static nextComponentId = 0
4041
static current
4142
constructor(tag, props, children) {
@@ -70,28 +71,30 @@ export class Component {
7071
children: this.children.length === 1 ? this.children[0] : this.children,
7172
}) || new Null()
7273
const paths = app.clearTrackState(trackId)
73-
this.mutationListener = app.addMutationListener(
74-
paths,
75-
(flushId, isAsync) => {
76-
app.eventHub.emitAsync('component:update', {
77-
componentId: this.componentId,
78-
componentInstanceId: this.componentInstanceId,
79-
name: this.name,
80-
flushId,
81-
paths: Array.from(paths),
82-
})
8374

84-
if (isAsync && !this.asyncRender) {
85-
this.asyncRender = requestAnimationFrame(() => {
86-
this.asyncRender = null
87-
this.reconcile(this, true)
88-
})
89-
} else if (!isAsync) {
90-
cancelAnimationFrame(this.asyncRender)
75+
this.mutationListener = app.addFlushListener(paths, (flushId, isAsync) => {
76+
if (!this.isMounted) {
77+
return
78+
}
79+
80+
app.eventHub.emitAsync('component:update', {
81+
componentId: this.componentId,
82+
componentInstanceId: this.componentInstanceId,
83+
name: this.name,
84+
flushId,
85+
paths: Array.from(paths),
86+
})
87+
88+
if (isAsync && !this.asyncRender) {
89+
this.asyncRender = requestAnimationFrame(() => {
90+
this.asyncRender = null
9191
this.reconcile(this, true)
92-
}
92+
})
93+
} else if (!isAsync) {
94+
cancelAnimationFrame(this.asyncRender)
95+
this.reconcile(this, true)
9396
}
94-
)
97+
})
9598
app.eventHub.emitAsync('component:add', {
9699
componentId: this.componentId,
97100
componentInstanceId: this.componentInstanceId,
@@ -104,6 +107,8 @@ export class Component {
104107
listener()
105108
}
106109

110+
this.isMounted = true
111+
107112
return this
108113
}
109114
addHook(hook) {
@@ -202,11 +207,13 @@ export class Component {
202207
return this.vtree instanceof Component ? this.vtree.getChild() : this.vtree
203208
}
204209
unmount() {
210+
this.isMounted = false
211+
cancelAnimationFrame(this.asyncRender)
212+
this.mutationListener.dispose()
205213
this.vtree.unmount()
206214
for (const listener of this.unmountListeners) {
207215
listener()
208216
}
209-
this.mutationListener.dispose()
210217
this.context.app.eventHub.emitAsync('component:remove', {
211218
componentId: this.componentId,
212219
componentInstanceId: this.componentInstanceId,

0 commit comments

Comments
 (0)