Skip to content

Commit 3effa4d

Browse files
authoredJul 15, 2019
pop() wasn't removing field meta state (#33)
1 parent d76d377 commit 3effa4d

File tree

2 files changed

+171
-6
lines changed

2 files changed

+171
-6
lines changed
 

‎src/pop.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,27 @@ const pop: Mutator<any> = (
77
{ changeValue }: Tools<any>
88
) => {
99
let result
10+
let removedIndex: ?number
1011
changeValue(state, name, (array: ?(any[])): ?(any[]) => {
1112
if (array) {
1213
if (!array.length) {
1314
return []
1415
}
15-
result = array[array.length - 1]
16-
return array.slice(0, array.length - 1)
16+
removedIndex = array.length - 1
17+
result = array[removedIndex]
18+
return array.slice(0, removedIndex)
1719
}
1820
})
21+
22+
// now we have to remove any subfields for our index,
23+
if (removedIndex !== undefined) {
24+
const pattern = new RegExp(`^${name}\\[${removedIndex}].*`)
25+
Object.keys(state.fields).forEach(key => {
26+
if (pattern.test(key)) {
27+
delete state.fields[key]
28+
}
29+
})
30+
}
1931
return result
2032
}
2133

‎src/pop.test.js

Lines changed: 157 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,28 @@
11
import pop from './pop'
2+
import { getIn, setIn } from 'final-form'
23

34
describe('pop', () => {
45
it('should call changeValue once', () => {
56
const changeValue = jest.fn()
6-
const state = {}
7+
const state = {
8+
formState: {
9+
values: {
10+
foo: ['one', 'two']
11+
}
12+
},
13+
fields: {
14+
'foo[0]': {
15+
name: 'foo[0]',
16+
touched: true,
17+
error: 'First Error'
18+
},
19+
'foo[1]': {
20+
name: 'foo[1]',
21+
touched: false,
22+
error: 'Second Error'
23+
}
24+
}
25+
}
726
const result = pop(['foo'], state, { changeValue })
827
expect(result).toBeUndefined()
928
expect(changeValue).toHaveBeenCalled()
@@ -15,7 +34,26 @@ describe('pop', () => {
1534

1635
it('should return undefined if array is undefined', () => {
1736
const changeValue = jest.fn()
18-
const returnValue = pop(['foo'], {}, { changeValue })
37+
const state = {
38+
formState: {
39+
values: {
40+
foo: ['one', 'two']
41+
}
42+
},
43+
fields: {
44+
'foo[0]': {
45+
name: 'foo[0]',
46+
touched: true,
47+
error: 'First Error'
48+
},
49+
'foo[1]': {
50+
name: 'foo[1]',
51+
touched: false,
52+
error: 'Second Error'
53+
}
54+
}
55+
}
56+
const returnValue = pop(['foo'], state, { changeValue })
1957
const op = changeValue.mock.calls[0][2]
2058
expect(returnValue).toBeUndefined()
2159
const result = op(undefined)
@@ -24,7 +62,26 @@ describe('pop', () => {
2462

2563
it('should return empty array if array is empty', () => {
2664
const changeValue = jest.fn()
27-
const returnValue = pop(['foo'], {}, { changeValue })
65+
const state = {
66+
formState: {
67+
values: {
68+
foo: ['one', 'two']
69+
}
70+
},
71+
fields: {
72+
'foo[0]': {
73+
name: 'foo[0]',
74+
touched: true,
75+
error: 'First Error'
76+
},
77+
'foo[1]': {
78+
name: 'foo[1]',
79+
touched: false,
80+
error: 'Second Error'
81+
}
82+
}
83+
}
84+
const returnValue = pop(['foo'], state, { changeValue })
2885
const op = changeValue.mock.calls[0][2]
2986
expect(returnValue).toBeUndefined()
3087
const result = op([])
@@ -37,9 +94,105 @@ describe('pop', () => {
3794
const changeValue = jest.fn((args, state, op) => {
3895
result = op(['a', 'b', 'c'])
3996
})
40-
const returnValue = pop(['foo'], {}, { changeValue })
97+
const state = {
98+
formState: {
99+
values: {
100+
foo: ['one', 'two']
101+
}
102+
},
103+
fields: {
104+
'foo[0]': {
105+
name: 'foo[0]',
106+
touched: true,
107+
error: 'First Error'
108+
},
109+
'foo[1]': {
110+
name: 'foo[1]',
111+
touched: false,
112+
error: 'Second Error'
113+
}
114+
}
115+
}
116+
const returnValue = pop(['foo'], state, { changeValue })
41117
expect(returnValue).toBe('c')
42118
expect(Array.isArray(result)).toBe(true)
43119
expect(result).toEqual(['a', 'b'])
44120
})
121+
122+
it('should pop value off the end of array and return it', () => {
123+
const array = ['a', 'b', 'c', 'd']
124+
// implementation of changeValue taken directly from Final Form
125+
const changeValue = (state, name, mutate) => {
126+
const before = getIn(state.formState.values, name)
127+
const after = mutate(before)
128+
state.formState.values = setIn(state.formState.values, name, after) || {}
129+
}
130+
const state = {
131+
formState: {
132+
values: {
133+
foo: array,
134+
anotherField: 42
135+
}
136+
},
137+
fields: {
138+
'foo[0]': {
139+
name: 'foo[0]',
140+
touched: true,
141+
error: 'A Error'
142+
},
143+
'foo[1]': {
144+
name: 'foo[1]',
145+
touched: false,
146+
error: 'B Error'
147+
},
148+
'foo[2]': {
149+
name: 'foo[2]',
150+
touched: true,
151+
error: 'C Error'
152+
},
153+
'foo[3]': {
154+
name: 'foo[3]',
155+
touched: false,
156+
error: 'D Error'
157+
},
158+
anotherField: {
159+
name: 'anotherField',
160+
touched: false
161+
}
162+
}
163+
}
164+
const returnValue = pop(['foo'], state, { changeValue })
165+
expect(returnValue).toBe('d')
166+
expect(Array.isArray(state.formState.values.foo)).toBe(true)
167+
expect(state.formState.values.foo).not.toBe(array) // copied
168+
expect(state).toEqual({
169+
formState: {
170+
values: {
171+
foo: ['a', 'b', 'c'],
172+
anotherField: 42
173+
}
174+
},
175+
fields: {
176+
'foo[0]': {
177+
name: 'foo[0]',
178+
touched: true,
179+
error: 'A Error'
180+
},
181+
'foo[1]': {
182+
name: 'foo[1]',
183+
touched: false,
184+
error: 'B Error'
185+
},
186+
'foo[2]': {
187+
name: 'foo[2]',
188+
touched: true,
189+
error: 'C Error'
190+
},
191+
anotherField: {
192+
name: 'anotherField',
193+
touched: false
194+
}
195+
}
196+
})
197+
})
45198
})

0 commit comments

Comments
 (0)
Please sign in to comment.