/
controller.tsx
125 lines (113 loc) 路 3.15 KB
/
controller.tsx
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import * as React from 'react';
import isBoolean from './utils/isBoolean';
import isUndefined from './utils/isUndefined';
import getInputValue from './logic/getInputValue';
import skipValidation from './logic/skipValidation';
import { useFormContext } from './useFormContext';
import { EVENTS, VALIDATION_MODE, VALUE } from './constants';
import { ControllerProps, EventFunction } from './types';
const Controller = ({
name,
rules,
as: InnerComponent,
onChange,
onBlur,
onChangeName = VALIDATION_MODE.onChange,
onBlurName = VALIDATION_MODE.onBlur,
valueName,
defaultValue,
control,
...rest
}: ControllerProps) => {
const methods = useFormContext() || {};
const {
defaultValues,
fields,
setValue,
register,
unregister,
errors,
mode: { isOnSubmit, isOnBlur },
reValidateMode: { isReValidateOnBlur, isReValidateOnSubmit },
formState: { isSubmitted },
} = control || methods.control;
const [value, setInputStateValue] = React.useState(
isUndefined(defaultValue) ? defaultValues[name] : defaultValue,
);
const valueRef = React.useRef(value);
const isCheckboxInput = isBoolean(value);
const shouldValidate = (isBlurEvent?: boolean) =>
!skipValidation({
hasError: !!errors[name],
isBlurEvent,
isOnBlur,
isOnSubmit,
isReValidateOnBlur,
isReValidateOnSubmit,
isSubmitted,
});
const commonTask = (target: any) => {
const data = getInputValue(target, isCheckboxInput);
setInputStateValue(data);
valueRef.current = data;
return data;
};
const eventWrapper = (event: EventFunction, eventName: string) => (
...arg: any
) => {
const data = commonTask(event(arg));
const isBlurEvent = eventName === EVENTS.BLUR;
setValue(name, data, shouldValidate(isBlurEvent));
};
const handleChange = (e: any) => {
const data = commonTask(e && e.target ? e.target : e);
setValue(name, data, shouldValidate());
};
const handleBlur = (e: any) => {
const data = commonTask(e && e.target ? e.target : e);
setValue(name, data, shouldValidate(true));
};
const registerField = () =>
register(
Object.defineProperty(
{
name,
},
VALUE,
{
set(data) {
setInputStateValue(data);
valueRef.current = data;
},
get() {
return valueRef.current;
},
},
),
{ ...rules },
);
if (!fields[name]) {
registerField();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
React.useEffect(() => () => unregister(name), []);
const props = {
name,
...rest,
...(onChange
? { [onChangeName]: eventWrapper(onChange, EVENTS.CHANGE) }
: { [onChangeName]: handleChange }),
...(isOnBlur || isReValidateOnBlur
? onBlur
? { [onBlurName]: eventWrapper(onBlur, EVENTS.BLUR) }
: { [onBlurName]: handleBlur }
: {}),
...{ [valueName || (isCheckboxInput ? 'checked' : VALUE)]: value },
};
return React.isValidElement(InnerComponent) ? (
React.cloneElement(InnerComponent, props)
) : (
<InnerComponent {...props} />
);
};
export { Controller };