Skip to content

Commit 8f0d084

Browse files
author
Ben Hamilton
committed
fixed issue with nested array or objects functions being removed or pointing to the wrong function.
1 parent 4a65647 commit 8f0d084

7 files changed

+104
-61
lines changed

src/move.test.js

+63-19
Original file line numberDiff line numberDiff line change
@@ -507,18 +507,38 @@ describe('move', () => {
507507
const after = mutate(before)
508508
state.formState.values = setIn(state.formState.values, name, after) || {}
509509
}
510+
function blur0() {}
511+
function change0() {}
512+
function focus0() {}
513+
function blur1() {}
514+
function change1() {}
515+
function focus1() {}
510516
const state = {
511517
formState: {
512518
values: {
513-
foo: [{ dog: 'apple dog', cat: 'apple cat', colors: [{ name: 'red'}, { name: 'blue'}], deep: { inside: { rock: 'black'}} },
514-
{ dog: 'banana dog', mouse: 'mickey', deep: { inside: { axe: 'golden' }} }]
519+
foo: [
520+
{
521+
dog: 'apple dog',
522+
cat: 'apple cat',
523+
colors: [{ name: 'red' }, { name: 'blue' }],
524+
deep: { inside: { rock: 'black' } }
525+
},
526+
{
527+
dog: 'banana dog',
528+
mouse: 'mickey',
529+
deep: { inside: { axe: 'golden' } }
530+
}
531+
]
515532
}
516533
},
517534
fields: {
518535
'foo[0].dog': {
519536
name: 'foo[0].dog',
520537
touched: true,
521-
error: 'Error A Dog'
538+
error: 'Error A Dog',
539+
blur: blur0,
540+
change: change0,
541+
focus: focus0
522542
},
523543
'foo[0].cat': {
524544
name: 'foo[0].cat',
@@ -548,21 +568,35 @@ describe('move', () => {
548568
'foo[1].mouse': {
549569
name: 'foo[1].mouse',
550570
touched: true,
551-
error: 'Error B Mickey'
571+
error: 'Error B Mickey',
572+
blur: blur1,
573+
change: change1,
574+
focus: focus1
552575
},
553576
'foo[1].deep.inside.axe': {
554577
name: 'foo[1].deep.inside.axe',
555578
touched: true,
556579
error: 'Error B Deep Inside Axe Golden'
557-
},
580+
}
558581
}
559582
}
560583
move(['foo', 0, 1], state, { changeValue })
561584
expect(state).toMatchObject({
562585
formState: {
563586
values: {
564-
foo: [{ dog: 'banana dog', mouse: 'mickey', deep: { inside: { axe: 'golden' }} },
565-
{ dog: 'apple dog', cat: 'apple cat', colors: [{ name: 'red'}, { name: 'blue'}], deep: { inside: { rock: 'black'}} }]
587+
foo: [
588+
{
589+
dog: 'banana dog',
590+
mouse: 'mickey',
591+
deep: { inside: { axe: 'golden' } }
592+
},
593+
{
594+
dog: 'apple dog',
595+
cat: 'apple cat',
596+
colors: [{ name: 'red' }, { name: 'blue' }],
597+
deep: { inside: { rock: 'black' } }
598+
}
599+
]
566600
}
567601
},
568602
fields: {
@@ -576,7 +610,10 @@ describe('move', () => {
576610
name: 'foo[0].mouse',
577611
touched: true,
578612
error: 'Error B Mickey',
579-
lastFieldState: undefined
613+
lastFieldState: undefined,
614+
blur: blur1,
615+
change: change1,
616+
focus: focus1
580617
},
581618
'foo[0].deep.inside.axe': {
582619
name: 'foo[0].deep.inside.axe',
@@ -587,7 +624,10 @@ describe('move', () => {
587624
name: 'foo[1].dog',
588625
touched: true,
589626
error: 'Error A Dog',
590-
lastFieldState: undefined
627+
lastFieldState: undefined,
628+
blur: blur0,
629+
change: change0,
630+
focus: focus0
591631
},
592632
'foo[1].cat': {
593633
name: 'foo[1].cat',
@@ -611,7 +651,7 @@ describe('move', () => {
611651
name: 'foo[1].deep.inside.rock',
612652
touched: true,
613653
error: 'Error A Deep Inside Rock Black'
614-
},
654+
}
615655
}
616656
})
617657
})
@@ -630,40 +670,44 @@ describe('move', () => {
630670
}
631671
},
632672
fields: {
633-
'foo[0]': {
673+
'foo[0].abc': {
634674
name: 'foo[0]',
635675
touched: true,
636676
error: 'Error A',
637677
lastFieldState: 'anything',
638-
change: () => 'foo[0]'
678+
change: () => 'customerId0',
679+
blur: () => 'foo[0].abc blur',
680+
focus: () => 'foo[0].abc focus'
639681
},
640682
'foo[1]': {
641683
name: 'foo[1]',
642684
touched: true,
643685
error: 'Error B',
644686
lastFieldState: 'anything',
645-
change: () => 'foo[1]'
687+
change: () => 'customerId1'
646688
},
647689
'foo[2]': {
648690
name: 'foo[2]',
649691
touched: false,
650692
error: 'Error C',
651693
lastFieldState: 'anything',
652-
change: () => 'foo[2]'
694+
change: () => 'customerId2'
653695
},
654696
'foo[3]': {
655697
name: 'foo[3]',
656698
touched: false,
657699
error: 'Error D',
658700
lastFieldState: 'anything',
659-
change: () => 'foo[3]'
701+
change: () => 'customerId3'
660702
}
661703
}
662704
}
663705
move(['foo', 0, 2], state, { changeValue })
664-
expect(state.fields['foo[0]'].change()).toBe('foo[0]')
665-
expect(state.fields['foo[1]'].change()).toBe('foo[1]')
666-
expect(state.fields['foo[2]'].change()).toBe('foo[2]')
667-
expect(state.fields['foo[3]'].change()).toBe('foo[3]')
706+
expect(state.fields['foo[0]'].change()).toBe('customerId1')
707+
expect(state.fields['foo[1]'].change()).toBe('customerId2')
708+
expect(state.fields['foo[2].abc'].change()).toBe('customerId0')
709+
expect(state.fields['foo[2].abc'].blur()).toBe('foo[0].abc blur')
710+
expect(state.fields['foo[2].abc'].focus()).toBe('foo[0].abc focus')
711+
expect(state.fields['foo[3]'].change()).toBe('customerId3')
668712
})
669713
})

src/moveFieldState.js

+10-11
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,28 @@ import type { MutableState } from 'final-form'
44
function moveFieldState(
55
state: MutableState<any>,
66
source: Object,
7-
destKey: string,
8-
oldState: MutableState<any> = state
7+
destKey: string
98
) {
109
delete state.fields[source.name]
1110
state.fields[destKey] = {
1211
...source,
1312
name: destKey,
14-
// prevent functions from being overwritten
15-
// if the state.fields[destKey] does not exist, it will be created
16-
// when that field gets registered, with its own change/blur/focus callbacks
17-
change: oldState.fields[destKey] && oldState.fields[destKey].change,
18-
blur: oldState.fields[destKey] && oldState.fields[destKey].blur,
19-
focus: oldState.fields[destKey] && oldState.fields[destKey].focus,
13+
// we want to preserve the source functions so they do not copy from the wrong state value
14+
// ie if we are moving foo[0] from 0 to 1, foo[0].change should be correctly moved under foo[1].change
15+
// if foo[0].change returned a specific hash statically we want foo[1].change to return the same hash not what foo[1].change previously returned
16+
change: source.change,
17+
blur: source.blur,
18+
focus: source.focus,
2019
lastFieldState: undefined // clearing lastFieldState forces renotification
2120
}
2221
if (!state.fields[destKey].change) {
23-
delete state.fields[destKey].change;
22+
delete state.fields[destKey].change
2423
}
2524
if (!state.fields[destKey].blur) {
26-
delete state.fields[destKey].blur;
25+
delete state.fields[destKey].blur
2726
}
2827
if (!state.fields[destKey].focus) {
29-
delete state.fields[destKey].focus;
28+
delete state.fields[destKey].focus
3029
}
3130
}
3231

src/remove.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ const remove: Mutator<any> = (
4343
delete state.fields[key]
4444
const decrementedKey = `${name}[${fieldIndex - 1}]${tokens[2]}`
4545
if (backup.fields[decrementedKey]) {
46-
moveFieldState(state, backup.fields[key], decrementedKey, backup)
46+
moveFieldState(state, backup.fields[key], decrementedKey)
4747
} else {
4848
// take care of setting the correct change, blur, focus, validators on new field
4949
renameField(state, key, decrementedKey)

src/remove.test.js

+12-12
Original file line numberDiff line numberDiff line change
@@ -137,18 +137,18 @@ describe('remove', () => {
137137
},
138138
'foo[1]': {
139139
name: 'foo[1]',
140-
blur: blur1,
141-
change: change1,
142-
focus: focus1,
140+
blur: blur2,
141+
change: change2,
142+
focus: focus2,
143143
touched: true,
144144
error: 'C Error',
145145
lastFieldState: undefined
146146
},
147147
'foo[2]': {
148148
name: 'foo[2]',
149-
blur: blur2,
150-
change: change2,
151-
focus: focus2,
149+
blur: blur3,
150+
change: change3,
151+
focus: focus3,
152152
touched: false,
153153
error: 'D Error',
154154
lastFieldState: undefined
@@ -252,18 +252,18 @@ describe('remove', () => {
252252
},
253253
'foo[0][1]': {
254254
name: 'foo[0][1]',
255-
blur: blur1,
256-
change: change1,
257-
focus: focus1,
255+
blur: blur2,
256+
change: change2,
257+
focus: focus2,
258258
touched: true,
259259
error: 'C Error',
260260
lastFieldState: undefined
261261
},
262262
'foo[0][2]': {
263263
name: 'foo[0][2]',
264-
blur: blur2,
265-
change: change2,
266-
focus: focus2,
264+
blur: blur3,
265+
change: change3,
266+
focus: focus3,
267267
touched: false,
268268
error: 'D Error',
269269
lastFieldState: undefined

src/removeBatch.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ const removeBatch: Mutator<any> = (
5050
// shift all higher ones down
5151
const decrementedKey = `${name}[${fieldIndex -
5252
countBelow(sortedIndexes, fieldIndex)}]${tokens[2]}`
53-
moveFieldState(newState, state.fields[key], decrementedKey, state)
53+
moveFieldState(newState, state.fields[key], decrementedKey)
5454
}
5555
} else {
5656
newState.fields[key] = state.fields[key]

src/removeBatch.test.js

+15-15
Original file line numberDiff line numberDiff line change
@@ -170,9 +170,9 @@ describe('removeBatch', () => {
170170
fields: {
171171
'foo[0]': {
172172
name: 'foo[0]',
173-
blur: blur0,
174-
change: change0,
175-
focus: focus0,
173+
blur: blur1,
174+
change: change1,
175+
focus: focus1,
176176
touched: false,
177177
error: 'Second Error',
178178
lastFieldState: undefined
@@ -307,18 +307,18 @@ describe('removeBatch', () => {
307307
},
308308
'foo[1]': {
309309
name: 'foo[1]',
310-
blur: blur1,
311-
change: change1,
312-
focus: focus1,
310+
blur: blur3,
311+
change: change3,
312+
focus: focus3,
313313
touched: false,
314314
error: 'D Error',
315315
lastFieldState: undefined
316316
},
317317
'foo[2]': {
318318
name: 'foo[2]',
319-
blur: blur2,
320-
change: change2,
321-
focus: focus2,
319+
blur: blur4,
320+
change: change4,
321+
focus: focus4,
322322
touched: true,
323323
error: 'E Error',
324324
lastFieldState: undefined
@@ -432,18 +432,18 @@ describe('removeBatch', () => {
432432
},
433433
'foo[0][1]': {
434434
name: 'foo[0][1]',
435-
blur: blur1,
436-
change: change1,
437-
focus: focus1,
435+
blur: blur3,
436+
change: change3,
437+
focus: focus3,
438438
touched: false,
439439
error: 'D Error',
440440
lastFieldState: undefined
441441
},
442442
'foo[0][2]': {
443443
name: 'foo[0][2]',
444-
blur: blur2,
445-
change: change2,
446-
focus: focus2,
444+
blur: blur4,
445+
change: change4,
446+
focus: focus4,
447447
touched: true,
448448
error: 'E Error',
449449
lastFieldState: undefined

src/swap.test.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -324,9 +324,9 @@ describe('swap', () => {
324324
}
325325
}
326326
swap(['foo', 0, 2], state, { changeValue })
327-
expect(state.fields['foo[0]'].change()).toBe('foo[0]')
327+
expect(state.fields['foo[0]'].change()).toBe('foo[2]')
328328
expect(state.fields['foo[1]'].change()).toBe('foo[1]')
329-
expect(state.fields['foo[2]'].change()).toBe('foo[2]')
329+
expect(state.fields['foo[2]'].change()).toBe('foo[0]')
330330
expect(state.fields['foo[3]'].change()).toBe('foo[3]')
331331
})
332332
})

0 commit comments

Comments
 (0)