Skip to content

Commit b32b947

Browse files
committed
Fix insert mutator removing fields unexpectedly.
1 parent 935fb43 commit b32b947

File tree

2 files changed

+47
-34
lines changed

2 files changed

+47
-34
lines changed

src/insert.js

+20-20
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,40 @@
11
// @flow
22
import type { MutableState, Mutator, Tools } from 'final-form'
3-
import moveFieldState from './moveFieldState'
3+
import copyField from './copyField'
44
import { escapeRegexTokens } from './utils'
55

66
const insert: Mutator<any> = (
77
[name, index, value]: any[],
88
state: MutableState<any>,
9-
{ changeValue, resetFieldState }: Tools<any>
9+
{ changeValue }: Tools<any>
1010
) => {
1111
changeValue(state, name, (array: ?(any[])): any[] => {
1212
const copy = [...(array || [])]
1313
copy.splice(index, 0, value)
1414
return copy
1515
})
1616

17-
const backup = { ...state.fields }
18-
1917
// now we have increment any higher indexes
2018
const pattern = new RegExp(`^${escapeRegexTokens(name)}\\[(\\d+)\\](.*)`)
21-
22-
// we need to increment high indices first so
23-
// lower indices won't overlap
24-
Object.keys(state.fields)
25-
.sort()
26-
.reverse()
27-
.forEach(key => {
28-
const tokens = pattern.exec(key)
29-
if (tokens) {
30-
const fieldIndex = Number(tokens[1])
31-
if (fieldIndex >= index) {
32-
// inc index one higher
33-
const incrementedKey = `${name}[${fieldIndex + 1}]${tokens[2]}`
34-
moveFieldState(state, backup[key], incrementedKey)
35-
}
19+
const newFields = {}
20+
Object.keys(state.fields).forEach(key => {
21+
const tokens = pattern.exec(key)
22+
if (tokens) {
23+
const fieldIndex = Number(tokens[1])
24+
if (fieldIndex >= index) {
25+
// Shift all higher indices up
26+
const incrementedKey = `${name}[${fieldIndex + 1}]${tokens[2]}`
27+
copyField(state.fields, key, newFields, incrementedKey)
28+
return
3629
}
37-
})
30+
}
31+
32+
// Keep this field that does not match the name,
33+
// or has index smaller than what is being inserted
34+
newFields[key] = state.fields[key]
35+
})
36+
37+
state.fields = newFields
3838
}
3939

4040
export default insert

src/insert.test.js

+27-14
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ describe('insert', () => {
8484
})
8585

8686
it('should increment other field data from the specified index', () => {
87-
const array = ['a', 'b', 'c', 'd']
87+
const array = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k']
8888
// implementation of changeValue taken directly from Final Form
8989
const changeValue = (state, name, mutate) => {
9090
const before = getIn(state.formState.values, name)
@@ -111,15 +111,15 @@ describe('insert', () => {
111111
touched: true,
112112
error: 'B Error'
113113
},
114-
'foo[2]': {
115-
name: 'foo[2]',
114+
'foo[9]': {
115+
name: 'foo[9]',
116116
touched: true,
117-
error: 'C Error'
117+
error: 'J Error'
118118
},
119-
'foo[3]': {
120-
name: 'foo[3]',
119+
'foo[10]': {
120+
name: 'foo[10]',
121121
touched: false,
122-
error: 'D Error'
122+
error: 'K Error'
123123
}
124124
}
125125
}
@@ -132,7 +132,20 @@ describe('insert', () => {
132132
expect(state).toEqual({
133133
formState: {
134134
values: {
135-
foo: ['a', 'NEWVALUE', 'b', 'c', 'd']
135+
foo: [
136+
'a',
137+
'NEWVALUE',
138+
'b',
139+
'c',
140+
'd',
141+
'e',
142+
'f',
143+
'g',
144+
'h',
145+
'i',
146+
'j',
147+
'k'
148+
]
136149
}
137150
},
138151
fields: {
@@ -147,16 +160,16 @@ describe('insert', () => {
147160
error: 'B Error',
148161
lastFieldState: undefined
149162
},
150-
'foo[3]': {
151-
name: 'foo[3]',
163+
'foo[10]': {
164+
name: 'foo[10]',
152165
touched: true,
153-
error: 'C Error',
166+
error: 'J Error',
154167
lastFieldState: undefined
155168
},
156-
'foo[4]': {
157-
name: 'foo[4]',
169+
'foo[11]': {
170+
name: 'foo[11]',
158171
touched: false,
159-
error: 'D Error',
172+
error: 'K Error',
160173
lastFieldState: undefined
161174
}
162175
}

0 commit comments

Comments
 (0)