Skip to content

Commit a86f0fb

Browse files
fix(overmind): fixes issue with deeply nested derived
1 parent 7a0ae97 commit a86f0fb

File tree

3 files changed

+64
-15
lines changed

3 files changed

+64
-15
lines changed

packages/node_modules/overmind/src/derived.test.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,4 +133,55 @@ describe('Derived', () => {
133133

134134
app.actions.changeFoo()
135135
})
136+
test('should track nested derived correctly', () => {
137+
expect.assertions(4)
138+
let runCount = 0
139+
const changeFoo: Action = ({ state }) => {
140+
state.foo = 'bar2'
141+
expect(state.upperFoo).toBe('BAR2')
142+
}
143+
144+
const derived: Derive<State, string> = (parent) => parent.foo.toUpperCase()
145+
146+
const nestedDerived: Derive<State, string> = (parent) =>
147+
parent.upperFoo + '!!!'
148+
149+
const config = {
150+
state: {
151+
foo: 'bar',
152+
nestedDerived,
153+
upperFoo: derived,
154+
},
155+
actions: {
156+
changeFoo,
157+
},
158+
}
159+
type Config = typeof config
160+
interface Action<Input = void> extends IAction<Config, Input> {}
161+
interface Derive<Parent extends IState, Value>
162+
extends IDerive<Config, Parent, Value> {}
163+
164+
const app = new Overmind(config)
165+
166+
const trackStateTree = app.getTrackStateTree()
167+
168+
function render() {
169+
runCount++
170+
if (runCount === 1) {
171+
expect(trackStateTree.state.nestedDerived).toBe('BAR!!!')
172+
} else {
173+
expect(trackStateTree.state.nestedDerived).toBe('BAR2!!!')
174+
}
175+
trackStateTree.stopTracking()
176+
console.log(trackStateTree.pathDependencies)
177+
}
178+
179+
trackStateTree.track(render)
180+
181+
render()
182+
183+
app.actions.changeFoo()
184+
185+
expect(runCount).toBe(2)
186+
})
136187
})

packages/node_modules/overmind/src/derived.ts

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ export class Derived {
2525
if (process.env.NODE_ENV === 'development') {
2626
boundEvaluate.dispose = () => {
2727
this.disposeOnMutation()
28-
this.trackStateTree.dispose()
2928
}
3029
}
3130

@@ -44,9 +43,7 @@ export class Derived {
4443
proxyStateTree: ProxyStateTree<any>,
4544
path
4645
) {
47-
if (!this.trackStateTree) {
48-
this.trackStateTree = proxyStateTree.getTrackStateTree()
49-
this.trackStateTree.shouldTrack = true
46+
if (!this.disposeOnMutation) {
5047
this.disposeOnMutation = proxyStateTree.onMutation(
5148
(_, paths, flushId) => {
5249
if (this.isDirty) {
@@ -77,13 +74,6 @@ export class Derived {
7774
this.isDirty = false
7875
this.paths = getPaths()
7976

80-
this.trackStateTree.clearTracking()
81-
82-
// We add the paths tracked to the derived
83-
for (let path of this.paths) {
84-
this.trackStateTree.addTrackingPath(path)
85-
}
86-
8777
if (process.env.NODE_ENV === 'development') {
8878
eventHub.emitAsync(EventType.DERIVED, {
8979
path,
@@ -93,11 +83,16 @@ export class Derived {
9383
})
9484
this.updateCount++
9585
}
96-
} else if (tree instanceof TrackStateTree) {
86+
}
87+
88+
if (tree instanceof TrackStateTree) {
9789
// If we access a cached value we have to make sure that we move
98-
// the tracked paths into the tree looking at it
90+
// the tracked paths into the tree looking at it, where
91+
// addTrackingPath is for initial tree and "trackPathListeners"
92+
// is for nested derived
9993
for (let path of this.paths) {
10094
tree.addTrackingPath(path)
95+
tree.trackPathListeners.forEach((cb) => cb(path))
10196
}
10297
}
10398

packages/node_modules/proxy-state-tree/src/TrackStateTree.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,13 @@ export class TrackStateTree<T extends object> implements ITrackStateTree<T> {
2424
const listener = (path) => {
2525
paths.add(path)
2626
}
27-
const index = this.trackPathListeners.push(listener) - 1
27+
this.trackPathListeners.push(listener)
2828

2929
return () => {
30-
this.trackPathListeners.splice(index, 1)
30+
this.trackPathListeners.splice(
31+
this.trackPathListeners.indexOf(listener),
32+
1
33+
)
3134

3235
return paths
3336
}

0 commit comments

Comments
 (0)