Skip to content

Commit 2fbdae7

Browse files
fix(proxy-state-tree): detect object add and removal of key as change to the object
1 parent 07e9e8e commit 2fbdae7

File tree

3 files changed

+67
-7
lines changed

3 files changed

+67
-7
lines changed

packages/node_modules/proxy-state-tree/src/index.test.ts

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ describe('ARRAYS', () => {
160160
}).toThrow()
161161
})
162162
test('should correctly keep track of changing indexes', () => {
163-
expect.assertions(3)
163+
expect.assertions(4)
164164
let listener
165165
let iterations = 0
166166
const tree = new ProxyStateTree({
@@ -209,6 +209,7 @@ describe('ARRAYS', () => {
209209
state.items.unshift({
210210
title: 'foo',
211211
})
212+
const currentProxy = state.items[0]
212213
tree.clearMutationTracking()
213214
tree.flush()
214215
tree.startMutationTracking()
@@ -219,8 +220,10 @@ describe('ARRAYS', () => {
219220
tree.flush()
220221
tree.startMutationTracking()
221222
state.items[1].title = 'wapah'
223+
const newProxy = state.items[1]
222224
tree.clearMutationTracking()
223225
tree.flush()
226+
expect(currentProxy).not.toBe(newProxy)
224227
})
225228
})
226229

@@ -522,6 +525,54 @@ describe('ITERATIONS', () => {
522525
const paths = tree.clearPathsTracking(trackId)
523526
expect(paths).toEqual(new Set(['items', 'items.foo', 'items.bar']))
524527
})
528+
test('should track new and deleted props on objects', () => {
529+
let runCount = 0
530+
let mutationListener
531+
expect.assertions(3)
532+
const tree = new ProxyStateTree({
533+
items: {},
534+
})
535+
const state = tree.get()
536+
function update() {
537+
const trackId = tree.startPathsTracking()
538+
Object.keys(state.items).forEach((key) => {
539+
state.items[key] // eslint-disable-line
540+
})
541+
const paths = tree.clearPathsTracking(trackId)
542+
543+
if (mutationListener) {
544+
mutationListener.update(paths)
545+
} else {
546+
mutationListener = tree.addMutationListener(paths, update)
547+
}
548+
549+
if (runCount === 1) {
550+
expect(paths).toEqual(new Set(['items', 'items.foo']))
551+
}
552+
if (runCount === 2) {
553+
expect(paths).toEqual(new Set(['items', 'items.foo', 'items.bar']))
554+
}
555+
if (runCount === 3) {
556+
expect(paths).toEqual(new Set(['items', 'items.bar']))
557+
}
558+
559+
runCount++
560+
}
561+
562+
update()
563+
tree.startMutationTracking()
564+
state.items.foo = 'bar'
565+
tree.clearMutationTracking()
566+
tree.flush()
567+
tree.startMutationTracking()
568+
state.items.bar = 'baz'
569+
tree.clearMutationTracking()
570+
tree.flush()
571+
tree.startMutationTracking()
572+
delete state.items.foo
573+
tree.clearMutationTracking()
574+
tree.flush()
575+
})
525576
test('should react to array mutation methods', () => {
526577
let reactionCount = 0
527578
const tree = new ProxyStateTree({

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

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ class ProxyStateTree {
1414
state: object
1515
options: Options
1616
pathDependencies: object
17+
objectChanges: Set<string>
1718
mutations: Mutation[]
1819
currentMutations: Mutation[]
1920
paths: Set<string>[]
20-
dirtyPaths: Set<string>
2121
status: STATUS
2222
proxy: any
2323
constructor(state: object, options: Options = { devmode: true }) {
@@ -27,7 +27,7 @@ class ProxyStateTree {
2727
this.mutations = []
2828
this.currentMutations = []
2929
this.paths = []
30-
this.dirtyPaths = new Set()
30+
this.objectChanges = new Set()
3131
this.status = STATUS.IDLE
3232
this.proxy = proxify(this, state)
3333
}
@@ -50,9 +50,10 @@ class ProxyStateTree {
5050
}
5151
}
5252
}
53-
for (let dirtyPath in this.dirtyPaths) {
54-
if (this.pathDependencies[dirtyPath]) {
55-
for (let callback of this.pathDependencies[dirtyPath]) {
53+
54+
for (let objectChange of this.objectChanges) {
55+
if (this.pathDependencies[objectChange]) {
56+
for (let callback of this.pathDependencies[objectChange]) {
5657
if (!pathCallbacksCalled.has(callback)) {
5758
pathCallbacksCalled.add(callback)
5859
callback()
@@ -62,7 +63,7 @@ class ProxyStateTree {
6263
}
6364
pathCallbacksCalled.clear()
6465
this.mutations.length = 0
65-
this.dirtyPaths.clear()
66+
this.objectChanges.clear()
6667

6768
return mutations
6869
}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,10 @@ function createObjectProxy(tree, value, path) {
121121
)
122122
}
123123
if (shouldTrackMutations(tree, nestedPath)) {
124+
if (!(prop in target)) {
125+
tree.objectChanges.add(path)
126+
}
127+
124128
tree.currentMutations.push({
125129
method: 'set',
126130
path: nestedPath,
@@ -139,6 +143,10 @@ function createObjectProxy(tree, value, path) {
139143
)
140144
}
141145
if (shouldTrackMutations(tree, nestedPath)) {
146+
if (!(prop in target)) {
147+
tree.objectChanges.add(path)
148+
}
149+
142150
tree.currentMutations.push({
143151
method: 'unset',
144152
path: nestedPath,

0 commit comments

Comments
 (0)