Skip to content

Commit 021c155

Browse files
authored
fix(core): fix ArrayField operation will trigger memo leak (#1831)
1 parent 6e541dc commit 021c155

File tree

3 files changed

+47
-7
lines changed

3 files changed

+47
-7
lines changed

packages/core/src/__tests__/array.spec.ts

+36
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { createForm } from '../'
2+
import { onFieldValueChange, onFormValuesChange } from '../effects'
23
import { attach } from './shared'
34

45
test('create array field', () => {
@@ -281,3 +282,38 @@ test('array field move api with children', async () => {
281282
expect(form.fields['array.0.name']).not.toBeUndefined()
282283
expect(form.fields['array.2.name']).toBeUndefined()
283284
})
285+
286+
test('array field remove memo leak', async () => {
287+
const handler = jest.fn()
288+
const valuesChange = jest.fn()
289+
const form = attach(
290+
createForm({
291+
effects() {
292+
onFormValuesChange(valuesChange)
293+
onFieldValueChange('*', handler)
294+
},
295+
})
296+
)
297+
const array = attach(
298+
form.createArrayField({
299+
name: 'array',
300+
})
301+
)
302+
await array.push('')
303+
attach(
304+
form.createField({
305+
name: '0',
306+
basePath: 'array',
307+
})
308+
)
309+
await array.remove(0)
310+
await array.push('')
311+
attach(
312+
form.createField({
313+
name: '0',
314+
basePath: 'array',
315+
})
316+
)
317+
expect(handler).toBeCalledTimes(1)
318+
expect(valuesChange).toBeCalledTimes(4)
319+
})

packages/core/src/models/ArrayField.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -52,35 +52,35 @@ export class ArrayField<
5252
if (!isArr(this.value)) return
5353
return batch(() => {
5454
const index = this.value.length - 1
55-
this.value.pop()
5655
spliceArrayState(this, {
5756
startIndex: index,
5857
deleteCount: 1,
5958
})
59+
this.value.pop()
6060
return this.onInput(this.value)
6161
})
6262
}
6363

6464
insert = async (index: number, ...items: any[]) => {
6565
if (!isArr(this.value)) return
6666
return batch(() => {
67-
this.value.splice(index, 0, ...items)
6867
spliceArrayState(this, {
6968
startIndex: index,
7069
insertCount: items.length,
7170
})
71+
this.value.splice(index, 0, ...items)
7272
return this.onInput(this.value)
7373
})
7474
}
7575

7676
remove = async (index: number) => {
7777
if (!isArr(this.value)) return
7878
return batch(() => {
79-
this.value.splice(index, 1)
8079
spliceArrayState(this, {
8180
startIndex: index,
8281
deleteCount: 1,
8382
})
83+
this.value.splice(index, 1)
8484
return this.onInput(this.value)
8585
})
8686
}
@@ -96,11 +96,11 @@ export class ArrayField<
9696
unshift = async (...items: any[]) => {
9797
if (!isArr(this.value)) return
9898
return batch(() => {
99-
this.value.unshift(...items)
10099
spliceArrayState(this, {
101100
startIndex: 0,
102101
insertCount: items.length,
103102
})
103+
this.value.unshift(...items)
104104
return this.onInput(this.value)
105105
})
106106
}

packages/core/src/shared/internals.ts

+7-3
Original file line numberDiff line numberDiff line change
@@ -662,16 +662,20 @@ export const triggerFormInitialValuesChange = (
662662
form: Form,
663663
change: DataChange
664664
) => {
665-
if (change.path[0] === 'initialValues') {
665+
const path = change.path
666+
if (path[path.length - 1] === 'length') return
667+
if (path[0] === 'initialValues') {
666668
if (change.type === 'add' || change.type === 'set') {
667-
applyValuesPatch(form, change.path.slice(1), change.value)
669+
applyValuesPatch(form, path.slice(1), change.value)
668670
}
669671
form.notify(LifeCycleTypes.ON_FORM_INITIAL_VALUES_CHANGE)
670672
}
671673
}
672674

673675
export const triggerFormValuesChange = (form: Form, change: DataChange) => {
674-
if (change.path[0] === 'values') {
676+
const path = change.path
677+
if (path[path.length - 1] === 'length') return
678+
if (path[0] === 'values') {
675679
form.notify(LifeCycleTypes.ON_FORM_VALUES_CHANGE)
676680
}
677681
}

0 commit comments

Comments
 (0)