-
-
Notifications
You must be signed in to change notification settings - Fork 70
/
Copy pathuseFieldArray.js
104 lines (95 loc) · 2.81 KB
/
useFieldArray.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// @flow
import { useForm, useField } from 'react-final-form'
import { fieldSubscriptionItems, ARRAY_ERROR } from 'final-form'
import type { Mutators } from 'final-form-arrays'
import type { FieldValidator, FieldSubscription } from 'final-form'
import type { FieldArrayRenderProps, UseFieldArrayConfig } from './types'
import defaultIsEqual from './defaultIsEqual'
import useConstant from './useConstant'
const all: FieldSubscription = fieldSubscriptionItems.reduce((result, key) => {
result[key] = true
return result
}, {})
const useFieldArray = (
name: string,
{
subscription = all,
defaultValue,
initialValue,
isEqual = defaultIsEqual,
validate: validateProp
}: UseFieldArrayConfig = {}
): FieldArrayRenderProps => {
const form = useForm('useFieldArray')
const formMutators: Mutators = form.mutators
const hasMutators = !!(formMutators && formMutators.push && formMutators.pop)
if (!hasMutators) {
throw new Error(
'Array mutators not found. You need to provide the mutators from final-form-arrays to your form'
)
}
const mutators = useConstant<Mutators>(() =>
// curry the field name onto all mutator calls
Object.keys(formMutators).reduce((result, key) => {
result[key] = (...args) => formMutators[key](name, ...args)
return result
}, {})
)
const validate: FieldValidator = useConstant(
() => (value, allValues, meta) => {
if (!validateProp) return undefined
const error = validateProp(value, allValues, meta)
if (!error || Array.isArray(error)) {
return error
} else {
const arrayError = []
// gross, but we have to set a string key on the array
;((arrayError: any): Object)[ARRAY_ERROR] = error
return arrayError
}
}
)
const {
meta: { length, ...meta },
input,
...fieldState
} = useField(name, {
subscription: { ...subscription, length: true },
defaultValue,
initialValue,
isEqual,
validate,
format: v => v
})
const forEach = (iterator: (name: string, index: number) => void): void => {
// required || for Flow, but results in uncovered line in Jest/Istanbul
// istanbul ignore next
const len = length || 0
for (let i = 0; i < len; i++) {
iterator(`${name}[${i}]`, i)
}
}
const map = (iterator: (name: string, index: number) => any): any[] => {
// required || for Flow, but results in uncovered line in Jest/Istanbul
// istanbul ignore next
const len = length || 0
const results: any[] = []
for (let i = 0; i < len; i++) {
results.push(iterator(`${name}[${i}]`, i))
}
return results
}
return {
fields: {
name,
forEach,
length: length || 0,
map,
...mutators,
...fieldState,
value: input.value
},
meta
}
}
export default useFieldArray