react-hook-form 7.18.0-next.0 → 7.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1213 -0
- package/README.md +29 -6
- package/dist/controller.d.ts +2 -2
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +232 -175
- package/dist/index.esm.js.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/dist/logic/generateWatchOutput.d.ts +2 -0
- package/dist/logic/schemaErrorLookup.d.ts +5 -0
- package/dist/logic/shouldSubscribeByName.d.ts +2 -0
- package/dist/types/controller.d.ts +10 -10
- package/dist/types/fieldArray.d.ts +1 -1
- package/dist/types/form.d.ts +17 -11
- package/dist/types/utils.d.ts +5 -3
- package/dist/useController.d.ts +2 -2
- package/dist/useSubscribe.d.ts +2 -3
- package/dist/useWatch.d.ts +4 -4
- package/dist/utils/cloneObject.d.ts +1 -1
- package/dist/utils/convertToArrayPayload.d.ts +1 -1
- package/dist/utils/createSubject.d.ts +13 -0
- package/dist/utils/get.d.ts +1 -1
- package/package.json +21 -23
- package/dist/utils/Subject.d.ts +0 -24
package/dist/index.esm.js
CHANGED
@@ -101,35 +101,39 @@ var shouldRenderFormState = (formStateData, _proxyFormState, isRoot) => {
|
|
101
101
|
(!isRoot || VALIDATION_MODE.all)));
|
102
102
|
};
|
103
103
|
|
104
|
-
var convertToArrayPayload = (value) => Array.isArray(value) ? value : [value];
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
104
|
+
var convertToArrayPayload = (value) => (Array.isArray(value) ? value : [value]);
|
105
|
+
|
106
|
+
var shouldSubscribeByName = (name, signalName) => !name ||
|
107
|
+
!signalName ||
|
108
|
+
name === signalName ||
|
109
|
+
convertToArrayPayload(name).some((currentName) => currentName &&
|
110
|
+
(currentName.startsWith(signalName) ||
|
111
|
+
signalName.startsWith(currentName)));
|
112
|
+
|
113
|
+
const tearDown = (_subscription) => {
|
114
|
+
if (_subscription.current) {
|
115
|
+
_subscription.current.unsubscribe();
|
116
|
+
_subscription.current = undefined;
|
110
117
|
}
|
111
118
|
};
|
112
|
-
const updateSubscriptionProps = ({
|
119
|
+
const updateSubscriptionProps = ({ _subscription, props }) => {
|
113
120
|
if (props.disabled) {
|
114
|
-
tearDown(
|
121
|
+
tearDown(_subscription);
|
115
122
|
}
|
116
|
-
else if (!
|
117
|
-
|
123
|
+
else if (!_subscription.current) {
|
124
|
+
_subscription.current = props.subject.subscribe({
|
118
125
|
next: props.callback,
|
119
126
|
});
|
120
127
|
}
|
121
128
|
};
|
122
129
|
function useSubscribe(props) {
|
123
|
-
const
|
124
|
-
|
125
|
-
|
126
|
-
_unsubscribe,
|
130
|
+
const _subscription = React.useRef();
|
131
|
+
updateSubscriptionProps({
|
132
|
+
_subscription,
|
127
133
|
props,
|
128
134
|
});
|
129
|
-
!props.skipEarlySubscription && _updateSubscription.current();
|
130
135
|
React.useEffect(() => {
|
131
|
-
|
132
|
-
return () => tearDown(_unsubscribe);
|
136
|
+
return () => tearDown(_subscription);
|
133
137
|
}, []);
|
134
138
|
}
|
135
139
|
|
@@ -149,9 +153,7 @@ function useFormState(props) {
|
|
149
153
|
_name.current = name;
|
150
154
|
useSubscribe({
|
151
155
|
disabled,
|
152
|
-
callback: (formState) => (
|
153
|
-
!formState.name ||
|
154
|
-
convertToArrayPayload(_name.current).includes(formState.name)) &&
|
156
|
+
callback: (formState) => shouldSubscribeByName(_name.current, formState.name) &&
|
155
157
|
shouldRenderFormState(formState, _localProxyFormState.current) &&
|
156
158
|
updateFormState(Object.assign(Object.assign({}, control._formState), formState)),
|
157
159
|
subject: control._subjects.state,
|
@@ -159,29 +161,71 @@ function useFormState(props) {
|
|
159
161
|
return getProxyFormState(formState, control._proxyFormState, _localProxyFormState.current, false);
|
160
162
|
}
|
161
163
|
|
164
|
+
var isString = (value) => typeof value === 'string';
|
165
|
+
|
166
|
+
function generateWatchOutput(names, _names, formValues, isGlobal) {
|
167
|
+
const isArray = Array.isArray(names);
|
168
|
+
if (isString(names)) {
|
169
|
+
isGlobal && _names.watch.add(names);
|
170
|
+
return get(formValues, names);
|
171
|
+
}
|
172
|
+
if (isArray) {
|
173
|
+
return names.map((fieldName) => (isGlobal && _names.watch.add(fieldName),
|
174
|
+
get(formValues, fieldName)));
|
175
|
+
}
|
176
|
+
isGlobal && (_names.watchAll = true);
|
177
|
+
return formValues;
|
178
|
+
}
|
179
|
+
|
180
|
+
function useWatch(props) {
|
181
|
+
const methods = useFormContext();
|
182
|
+
const { control = methods.control, name, defaultValue, disabled, } = props || {};
|
183
|
+
const _name = React.useRef(name);
|
184
|
+
_name.current = name;
|
185
|
+
useSubscribe({
|
186
|
+
disabled,
|
187
|
+
subject: control._subjects.watch,
|
188
|
+
callback: (formState) => {
|
189
|
+
if (shouldSubscribeByName(_name.current, formState.name)) {
|
190
|
+
const fieldValues = generateWatchOutput(_name.current, control._names, control._formValues);
|
191
|
+
updateValue(isObject(fieldValues)
|
192
|
+
? Object.assign({}, fieldValues) : Array.isArray(fieldValues)
|
193
|
+
? [...fieldValues]
|
194
|
+
: fieldValues);
|
195
|
+
}
|
196
|
+
},
|
197
|
+
});
|
198
|
+
const [value, updateValue] = React.useState(isUndefined(defaultValue)
|
199
|
+
? control._getWatch(name)
|
200
|
+
: defaultValue);
|
201
|
+
React.useEffect(() => {
|
202
|
+
control._removeUnmounted();
|
203
|
+
});
|
204
|
+
return value;
|
205
|
+
}
|
206
|
+
|
162
207
|
function useController(props) {
|
163
208
|
const methods = useFormContext();
|
164
209
|
const { name, control = methods.control, shouldUnregister } = props;
|
165
|
-
const
|
210
|
+
const value = useWatch({
|
211
|
+
control,
|
212
|
+
name,
|
213
|
+
defaultValue: get(control._formValues, name, get(control._defaultValues, name, props.defaultValue)),
|
214
|
+
});
|
166
215
|
const formState = useFormState({
|
167
|
-
control
|
216
|
+
control,
|
168
217
|
name,
|
169
218
|
});
|
170
219
|
const _name = React.useRef(name);
|
171
220
|
_name.current = name;
|
172
|
-
useSubscribe({
|
173
|
-
subject: control._subjects.control,
|
174
|
-
callback: (data) => (!data.name || _name.current === data.name) &&
|
175
|
-
setInputStateValue(get(data.values, _name.current)),
|
176
|
-
});
|
177
221
|
const registerProps = control.register(name, Object.assign(Object.assign({}, props.rules), { value }));
|
178
|
-
const updateMounted = React.useCallback((name, value) => {
|
179
|
-
const field = get(control._fields, name);
|
180
|
-
if (field) {
|
181
|
-
field._f.mount = value;
|
182
|
-
}
|
183
|
-
}, [control]);
|
184
222
|
React.useEffect(() => {
|
223
|
+
const updateMounted = (name, value) => {
|
224
|
+
const field = get(control._fields, name);
|
225
|
+
if (field) {
|
226
|
+
field._f.mount = value;
|
227
|
+
}
|
228
|
+
};
|
185
229
|
updateMounted(name, true);
|
186
230
|
return () => {
|
187
231
|
const _shouldUnregisterField = control._options.shouldUnregister || shouldUnregister;
|
@@ -194,15 +238,13 @@ function useController(props) {
|
|
194
238
|
updateMounted(name, false);
|
195
239
|
}
|
196
240
|
};
|
197
|
-
}, [name, control, shouldUnregister
|
241
|
+
}, [name, control, shouldUnregister]);
|
198
242
|
return {
|
199
243
|
field: {
|
200
244
|
onChange: (event) => {
|
201
|
-
const value = getControllerValue(event);
|
202
|
-
setInputStateValue(value);
|
203
245
|
registerProps.onChange({
|
204
246
|
target: {
|
205
|
-
value,
|
247
|
+
value: getControllerValue(event),
|
206
248
|
name: name,
|
207
249
|
},
|
208
250
|
type: EVENTS.CHANGE,
|
@@ -373,6 +415,7 @@ const useFieldArray = (props) => {
|
|
373
415
|
const [fields, setFields] = React.useState(mapIds(control._getFieldArray(name), keyName));
|
374
416
|
const _fieldIds = React.useRef(fields);
|
375
417
|
const _name = React.useRef(name);
|
418
|
+
const _actioned = React.useRef(false);
|
376
419
|
_name.current = name;
|
377
420
|
_fieldIds.current = fields;
|
378
421
|
control._names.array.add(name);
|
@@ -383,10 +426,10 @@ const useFieldArray = (props) => {
|
|
383
426
|
}
|
384
427
|
},
|
385
428
|
subject: control._subjects.array,
|
386
|
-
skipEarlySubscription: true,
|
387
429
|
});
|
388
430
|
const updateValues = React.useCallback((updatedFieldArrayValuesWithKey) => {
|
389
431
|
const updatedFieldArrayValues = omitKeys(updatedFieldArrayValuesWithKey, keyName);
|
432
|
+
_actioned.current = true;
|
390
433
|
set(control._formValues, name, updatedFieldArrayValues);
|
391
434
|
setFields(updatedFieldArrayValuesWithKey);
|
392
435
|
return updatedFieldArrayValues;
|
@@ -462,6 +505,17 @@ const useFieldArray = (props) => {
|
|
462
505
|
}
|
463
506
|
}
|
464
507
|
}
|
508
|
+
if (_actioned.current) {
|
509
|
+
control._executeSchema([name]).then((result) => {
|
510
|
+
const error = get(result.errors, name);
|
511
|
+
if (error && error.type && !get(control._formState.errors, name)) {
|
512
|
+
set(control._formState.errors, name, error);
|
513
|
+
control._subjects.state.next({
|
514
|
+
errors: control._formState.errors,
|
515
|
+
});
|
516
|
+
}
|
517
|
+
});
|
518
|
+
}
|
465
519
|
control._subjects.watch.next({
|
466
520
|
name,
|
467
521
|
values: control._formValues,
|
@@ -519,6 +573,34 @@ function cloneObject(data) {
|
|
519
573
|
return copy;
|
520
574
|
}
|
521
575
|
|
576
|
+
function createSubject() {
|
577
|
+
let _observers = [];
|
578
|
+
const next = (value) => {
|
579
|
+
for (const observer of _observers) {
|
580
|
+
observer.next(value);
|
581
|
+
}
|
582
|
+
};
|
583
|
+
const subscribe = (observer) => {
|
584
|
+
_observers.push(observer);
|
585
|
+
return {
|
586
|
+
unsubscribe: () => {
|
587
|
+
_observers = _observers.filter((o) => o !== observer);
|
588
|
+
},
|
589
|
+
};
|
590
|
+
};
|
591
|
+
const unsubscribe = () => {
|
592
|
+
_observers = [];
|
593
|
+
};
|
594
|
+
return {
|
595
|
+
get observers() {
|
596
|
+
return _observers;
|
597
|
+
},
|
598
|
+
next,
|
599
|
+
subscribe,
|
600
|
+
unsubscribe,
|
601
|
+
};
|
602
|
+
}
|
603
|
+
|
522
604
|
var isPrimitive = (value) => isNullOrUndefined(value) || !isObjectType(value);
|
523
605
|
|
524
606
|
function deepEqual(object1, object2) {
|
@@ -562,6 +644,8 @@ var getValidationModes = (mode) => ({
|
|
562
644
|
|
563
645
|
var isBoolean = (value) => typeof value === 'boolean';
|
564
646
|
|
647
|
+
var isFileInput = (element) => element.type === 'file';
|
648
|
+
|
565
649
|
var isHTMLElement = (value) => value instanceof HTMLElement;
|
566
650
|
|
567
651
|
var isMultipleSelect = (element) => element.type === `select-multiple`;
|
@@ -570,59 +654,11 @@ var isRadioInput = (element) => element.type === 'radio';
|
|
570
654
|
|
571
655
|
var isRadioOrCheckboxFunction = (ref) => isRadioInput(ref) || isCheckBoxInput(ref);
|
572
656
|
|
573
|
-
var isString = (value) => typeof value === 'string';
|
574
|
-
|
575
657
|
var isWeb = typeof window !== 'undefined' &&
|
576
658
|
typeof window.HTMLElement !== 'undefined' &&
|
577
659
|
typeof document !== 'undefined';
|
578
660
|
|
579
|
-
var live = (ref) =>
|
580
|
-
|
581
|
-
class Subscription {
|
582
|
-
constructor() {
|
583
|
-
this.tearDowns = [];
|
584
|
-
}
|
585
|
-
add(tearDown) {
|
586
|
-
this.tearDowns.push(tearDown);
|
587
|
-
}
|
588
|
-
unsubscribe() {
|
589
|
-
for (const teardown of this.tearDowns) {
|
590
|
-
teardown();
|
591
|
-
}
|
592
|
-
this.tearDowns = [];
|
593
|
-
}
|
594
|
-
}
|
595
|
-
class Subscriber {
|
596
|
-
constructor(observer, subscription) {
|
597
|
-
this.observer = observer;
|
598
|
-
this.closed = false;
|
599
|
-
subscription.add(() => (this.closed = true));
|
600
|
-
}
|
601
|
-
next(value) {
|
602
|
-
if (!this.closed) {
|
603
|
-
this.observer.next(value);
|
604
|
-
}
|
605
|
-
}
|
606
|
-
}
|
607
|
-
class Subject {
|
608
|
-
constructor() {
|
609
|
-
this.observers = [];
|
610
|
-
}
|
611
|
-
next(value) {
|
612
|
-
for (const observer of this.observers) {
|
613
|
-
observer.next(value);
|
614
|
-
}
|
615
|
-
}
|
616
|
-
subscribe(observer) {
|
617
|
-
const subscription = new Subscription();
|
618
|
-
const subscriber = new Subscriber(observer, subscription);
|
619
|
-
this.observers.push(subscriber);
|
620
|
-
return subscription;
|
621
|
-
}
|
622
|
-
unsubscribe() {
|
623
|
-
this.observers = [];
|
624
|
-
}
|
625
|
-
}
|
661
|
+
var live = (ref) => isHTMLElement(ref) && document.contains(ref);
|
626
662
|
|
627
663
|
function baseGet(object, updatePath) {
|
628
664
|
const length = updatePath.slice(0, -1).length;
|
@@ -663,8 +699,6 @@ function unset(object, path) {
|
|
663
699
|
return object;
|
664
700
|
}
|
665
701
|
|
666
|
-
var isFileInput = (element) => element.type === 'file';
|
667
|
-
|
668
702
|
const defaultResult = {
|
669
703
|
value: false,
|
670
704
|
isValid: false,
|
@@ -758,6 +792,35 @@ var hasValidation = (options) => options.mount &&
|
|
758
792
|
options.pattern ||
|
759
793
|
options.validate);
|
760
794
|
|
795
|
+
function schemaErrorLookup(errors, _fields, name) {
|
796
|
+
const error = get(errors, name);
|
797
|
+
if (error || isKey(name)) {
|
798
|
+
return {
|
799
|
+
error,
|
800
|
+
name,
|
801
|
+
};
|
802
|
+
}
|
803
|
+
const names = name.split('.');
|
804
|
+
while (names.length) {
|
805
|
+
const fieldName = names.join('.');
|
806
|
+
const field = get(_fields, fieldName);
|
807
|
+
const foundError = get(errors, fieldName);
|
808
|
+
if (field && !Array.isArray(field) && name !== fieldName) {
|
809
|
+
return { name };
|
810
|
+
}
|
811
|
+
if (foundError && foundError.type) {
|
812
|
+
return {
|
813
|
+
name: fieldName,
|
814
|
+
error: foundError,
|
815
|
+
};
|
816
|
+
}
|
817
|
+
names.pop();
|
818
|
+
}
|
819
|
+
return {
|
820
|
+
name,
|
821
|
+
};
|
822
|
+
}
|
823
|
+
|
761
824
|
function deepMerge(target, source) {
|
762
825
|
if (isPrimitive(target) || isPrimitive(source)) {
|
763
826
|
return source;
|
@@ -1027,10 +1090,9 @@ function createFormControl(props = {}) {
|
|
1027
1090
|
errors: false,
|
1028
1091
|
};
|
1029
1092
|
const _subjects = {
|
1030
|
-
watch:
|
1031
|
-
|
1032
|
-
|
1033
|
-
state: new Subject(),
|
1093
|
+
watch: createSubject(),
|
1094
|
+
array: createSubject(),
|
1095
|
+
state: createSubject(),
|
1034
1096
|
};
|
1035
1097
|
const validationModeBeforeSubmit = getValidationModes(_options.mode);
|
1036
1098
|
const validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
|
@@ -1047,7 +1109,7 @@ function createFormControl(props = {}) {
|
|
1047
1109
|
let isValid = false;
|
1048
1110
|
if (_proxyFormState.isValid) {
|
1049
1111
|
isValid = _options.resolver
|
1050
|
-
? isEmptyObject((await
|
1112
|
+
? isEmptyObject((await _executeSchema()).errors)
|
1051
1113
|
: await executeBuildInValidation(_fields, true);
|
1052
1114
|
if (!shouldSkipRender && isValid !== _formState.isValid) {
|
1053
1115
|
_formState.isValid = isValid;
|
@@ -1166,11 +1228,11 @@ function createFormControl(props = {}) {
|
|
1166
1228
|
validateFields = {};
|
1167
1229
|
}
|
1168
1230
|
};
|
1169
|
-
const
|
1231
|
+
const _executeSchema = async (name) => _options.resolver
|
1170
1232
|
? await _options.resolver(Object.assign({}, _formValues), _options.context, getResolverOptions(name || _names.mount, _fields, _options.criteriaMode, _options.shouldUseNativeValidation))
|
1171
1233
|
: {};
|
1172
|
-
const
|
1173
|
-
const { errors } = await
|
1234
|
+
const executeSchemaAndUpdateState = async (names) => {
|
1235
|
+
const { errors } = await _executeSchema();
|
1174
1236
|
if (names) {
|
1175
1237
|
for (const name of names) {
|
1176
1238
|
const error = get(errors, name);
|
@@ -1216,7 +1278,9 @@ function createFormControl(props = {}) {
|
|
1216
1278
|
for (const name of _names.unMount) {
|
1217
1279
|
const field = get(_fields, name);
|
1218
1280
|
field &&
|
1219
|
-
(field._f.refs
|
1281
|
+
(field._f.refs
|
1282
|
+
? field._f.refs.every((ref) => !live(ref))
|
1283
|
+
: !live(field._f.ref)) &&
|
1220
1284
|
unregister(name);
|
1221
1285
|
}
|
1222
1286
|
_names.unMount = new Set();
|
@@ -1231,16 +1295,10 @@ function createFormControl(props = {}) {
|
|
1231
1295
|
: isString(names)
|
1232
1296
|
? { [names]: defaultValue }
|
1233
1297
|
: defaultValue));
|
1234
|
-
|
1235
|
-
const result = convertToArrayPayload(names).map((fieldName) => (isGlobal && _names.watch.add(fieldName),
|
1236
|
-
get(fieldValues, fieldName)));
|
1237
|
-
return Array.isArray(names) ? result : result[0];
|
1238
|
-
}
|
1239
|
-
isGlobal && (_names.watchAll = true);
|
1240
|
-
return fieldValues;
|
1298
|
+
return generateWatchOutput(names, _names, fieldValues, isGlobal);
|
1241
1299
|
};
|
1242
|
-
const _getFieldArray = (name) => get(_stateFlags.mount ? _formValues : _defaultValues, name, []);
|
1243
|
-
const setFieldValue = (name, value, options = {}
|
1300
|
+
const _getFieldArray = (name) => get(_stateFlags.mount ? _formValues : _defaultValues, name, props.shouldUnregister ? get(_defaultValues, name, []) : []);
|
1301
|
+
const setFieldValue = (name, value, options = {}) => {
|
1244
1302
|
const field = get(_fields, name);
|
1245
1303
|
let fieldValue = value;
|
1246
1304
|
if (field) {
|
@@ -1251,7 +1309,10 @@ function createFormControl(props = {}) {
|
|
1251
1309
|
isWeb && isHTMLElement(fieldReference.ref) && isNullOrUndefined(value)
|
1252
1310
|
? ''
|
1253
1311
|
: value;
|
1254
|
-
if (
|
1312
|
+
if (isFileInput(fieldReference.ref) && !isString(fieldValue)) {
|
1313
|
+
fieldReference.ref.files = fieldValue;
|
1314
|
+
}
|
1315
|
+
else if (isMultipleSelect(fieldReference.ref)) {
|
1255
1316
|
[...fieldReference.ref.options].forEach((selectRef) => (selectRef.selected = fieldValue.includes(selectRef.value)));
|
1256
1317
|
}
|
1257
1318
|
else if (fieldReference.refs) {
|
@@ -1269,11 +1330,6 @@ function createFormControl(props = {}) {
|
|
1269
1330
|
else {
|
1270
1331
|
fieldReference.ref.value = fieldValue;
|
1271
1332
|
}
|
1272
|
-
shouldRender &&
|
1273
|
-
_subjects.control.next({
|
1274
|
-
values: _formValues,
|
1275
|
-
name,
|
1276
|
-
});
|
1277
1333
|
}
|
1278
1334
|
}
|
1279
1335
|
(options.shouldDirty || options.shouldTouch) &&
|
@@ -1290,7 +1346,7 @@ function createFormControl(props = {}) {
|
|
1290
1346
|
(field && !field._f)) &&
|
1291
1347
|
!isDateObject(fieldValue)
|
1292
1348
|
? setValues(fieldName, fieldValue, options)
|
1293
|
-
: setFieldValue(fieldName, fieldValue, options
|
1349
|
+
: setFieldValue(fieldName, fieldValue, options);
|
1294
1350
|
}
|
1295
1351
|
};
|
1296
1352
|
const setValue = (name, value, options = {}) => {
|
@@ -1315,7 +1371,7 @@ function createFormControl(props = {}) {
|
|
1315
1371
|
else {
|
1316
1372
|
field && !field._f && !isNullOrUndefined(value)
|
1317
1373
|
? setValues(name, value, options)
|
1318
|
-
: setFieldValue(name, value, options
|
1374
|
+
: setFieldValue(name, value, options);
|
1319
1375
|
}
|
1320
1376
|
isFieldWatched(name) && _subjects.state.next({});
|
1321
1377
|
_subjects.watch.next({
|
@@ -1362,18 +1418,11 @@ function createFormControl(props = {}) {
|
|
1362
1418
|
isValidating: true,
|
1363
1419
|
});
|
1364
1420
|
if (_options.resolver) {
|
1365
|
-
const { errors } = await
|
1366
|
-
|
1367
|
-
|
1368
|
-
|
1369
|
-
|
1370
|
-
if (Array.isArray(parentField) &&
|
1371
|
-
parentField.every((field) => field._f && isCheckBoxInput(field._f.ref))) {
|
1372
|
-
const parentError = get(errors, parentNodeName, {});
|
1373
|
-
parentError.type && (error = parentError);
|
1374
|
-
name = parentNodeName;
|
1375
|
-
}
|
1376
|
-
}
|
1421
|
+
const { errors } = await _executeSchema([name]);
|
1422
|
+
const previousErrorLookupResult = schemaErrorLookup(_formState.errors, _fields, name);
|
1423
|
+
const errorLookupResult = schemaErrorLookup(errors, _fields, previousErrorLookupResult.name || name);
|
1424
|
+
error = errorLookupResult.error;
|
1425
|
+
name = errorLookupResult.name;
|
1377
1426
|
isValid = isEmptyObject(errors);
|
1378
1427
|
}
|
1379
1428
|
else {
|
@@ -1392,7 +1441,7 @@ function createFormControl(props = {}) {
|
|
1392
1441
|
isValidating: true,
|
1393
1442
|
});
|
1394
1443
|
if (_options.resolver) {
|
1395
|
-
const errors = await
|
1444
|
+
const errors = await executeSchemaAndUpdateState(isUndefined(name) ? name : fieldNames);
|
1396
1445
|
isValid = isEmptyObject(errors);
|
1397
1446
|
validationResult = name
|
1398
1447
|
? !fieldNames.some((name) => get(errors, name))
|
@@ -1403,12 +1452,15 @@ function createFormControl(props = {}) {
|
|
1403
1452
|
const field = get(_fields, fieldName);
|
1404
1453
|
return await executeBuildInValidation(field && field._f ? { [fieldName]: field } : field);
|
1405
1454
|
}))).every(Boolean);
|
1406
|
-
_updateValid();
|
1455
|
+
!(!validationResult && !_formState.isValid) && _updateValid();
|
1407
1456
|
}
|
1408
1457
|
else {
|
1409
1458
|
validationResult = isValid = await executeBuildInValidation(_fields);
|
1410
1459
|
}
|
1411
|
-
_subjects.state.next(Object.assign(Object.assign({}, (!isString(name) ||
|
1460
|
+
_subjects.state.next(Object.assign(Object.assign(Object.assign({}, (!isString(name) ||
|
1461
|
+
(_proxyFormState.isValid && isValid !== _formState.isValid)
|
1462
|
+
? {}
|
1463
|
+
: { name })), (_options.resolver ? { isValid } : {})), { errors: _formState.errors, isValidating: false }));
|
1412
1464
|
options.shouldFocus &&
|
1413
1465
|
!validationResult &&
|
1414
1466
|
focusFieldBy(_fields, (key) => get(_formState.errors, key), name ? fieldNames : _names.mount);
|
@@ -1428,6 +1480,7 @@ function createFormControl(props = {}) {
|
|
1428
1480
|
: (_formState.errors = {});
|
1429
1481
|
_subjects.state.next({
|
1430
1482
|
errors: _formState.errors,
|
1483
|
+
isValid: true,
|
1431
1484
|
});
|
1432
1485
|
};
|
1433
1486
|
const setError = (name, error, options) => {
|
@@ -1472,7 +1525,8 @@ function createFormControl(props = {}) {
|
|
1472
1525
|
_f: Object.assign(Object.assign(Object.assign({}, (field && field._f ? field._f : { ref: { name } })), { name, mount: true }), options),
|
1473
1526
|
});
|
1474
1527
|
_names.mount.add(name);
|
1475
|
-
!isUndefined(options.value) &&
|
1528
|
+
!isUndefined(options.value) &&
|
1529
|
+
set(_formValues, name, get(_formValues, name, options.value));
|
1476
1530
|
field
|
1477
1531
|
? isBoolean(options.disabled) &&
|
1478
1532
|
set(_formValues, name, options.disabled
|
@@ -1502,7 +1556,7 @@ function createFormControl(props = {}) {
|
|
1502
1556
|
field = {
|
1503
1557
|
_f: isRadioOrCheckbox
|
1504
1558
|
? Object.assign(Object.assign({}, field._f), { refs: [
|
1505
|
-
...compact(field._f.refs || []).filter(
|
1559
|
+
...compact(field._f.refs || []).filter(live),
|
1506
1560
|
fieldRef,
|
1507
1561
|
], ref: { type: fieldRef.type, name } }) : Object.assign(Object.assign({}, field._f), { ref: fieldRef }),
|
1508
1562
|
};
|
@@ -1534,7 +1588,7 @@ function createFormControl(props = {}) {
|
|
1534
1588
|
});
|
1535
1589
|
try {
|
1536
1590
|
if (_options.resolver) {
|
1537
|
-
const { errors, values } = await
|
1591
|
+
const { errors, values } = await _executeSchema();
|
1538
1592
|
_formState.errors = errors;
|
1539
1593
|
fieldValues = values;
|
1540
1594
|
}
|
@@ -1570,10 +1624,35 @@ function createFormControl(props = {}) {
|
|
1570
1624
|
});
|
1571
1625
|
}
|
1572
1626
|
};
|
1627
|
+
const resetField = (name, options = {}) => {
|
1628
|
+
if (isUndefined(options.defaultValue)) {
|
1629
|
+
setValue(name, get(_defaultValues, name));
|
1630
|
+
}
|
1631
|
+
else {
|
1632
|
+
setValue(name, options.defaultValue);
|
1633
|
+
set(_defaultValues, name, options.defaultValue);
|
1634
|
+
}
|
1635
|
+
if (!options.keepTouched) {
|
1636
|
+
unset(_formState.touchedFields, name);
|
1637
|
+
}
|
1638
|
+
if (!options.keepDirty) {
|
1639
|
+
unset(_formState.dirtyFields, name);
|
1640
|
+
_formState.isDirty = options.defaultValue
|
1641
|
+
? _getDirty(name, get(_defaultValues, name))
|
1642
|
+
: _getDirty();
|
1643
|
+
}
|
1644
|
+
if (!options.keepError) {
|
1645
|
+
unset(_formState.errors, name);
|
1646
|
+
_proxyFormState.isValid && _updateValid();
|
1647
|
+
}
|
1648
|
+
_subjects.state.next(Object.assign({}, _formState));
|
1649
|
+
};
|
1573
1650
|
const reset = (formValues, keepStateOptions = {}) => {
|
1574
|
-
const hasUpdatedFormValues = !isEmptyObject(formValues);
|
1575
1651
|
const updatedValues = formValues || _defaultValues;
|
1576
1652
|
const cloneUpdatedValues = cloneObject(updatedValues);
|
1653
|
+
const values = !isEmptyObject(formValues)
|
1654
|
+
? cloneUpdatedValues
|
1655
|
+
: _defaultValues;
|
1577
1656
|
if (!keepStateOptions.keepDefaultValues) {
|
1578
1657
|
_defaultValues = updatedValues;
|
1579
1658
|
}
|
@@ -1594,14 +1673,17 @@ function createFormControl(props = {}) {
|
|
1594
1673
|
}
|
1595
1674
|
}
|
1596
1675
|
}
|
1597
|
-
_formValues = props.shouldUnregister
|
1676
|
+
_formValues = props.shouldUnregister
|
1677
|
+
? keepStateOptions.keepDefaultValues
|
1678
|
+
? cloneObject(_defaultValues)
|
1679
|
+
: {}
|
1680
|
+
: cloneUpdatedValues;
|
1598
1681
|
_fields = {};
|
1599
|
-
_subjects.
|
1600
|
-
values
|
1682
|
+
_subjects.watch.next({
|
1683
|
+
values,
|
1601
1684
|
});
|
1602
|
-
_subjects.watch.next({});
|
1603
1685
|
_subjects.array.next({
|
1604
|
-
values
|
1686
|
+
values,
|
1605
1687
|
});
|
1606
1688
|
}
|
1607
1689
|
_names = {
|
@@ -1619,14 +1701,16 @@ function createFormControl(props = {}) {
|
|
1619
1701
|
isDirty: keepStateOptions.keepDirty
|
1620
1702
|
? _formState.isDirty
|
1621
1703
|
: keepStateOptions.keepDefaultValues
|
1622
|
-
? deepEqual(formValues, _defaultValues)
|
1704
|
+
? !deepEqual(formValues, _defaultValues)
|
1623
1705
|
: false,
|
1624
1706
|
isSubmitted: keepStateOptions.keepIsSubmitted
|
1625
1707
|
? _formState.isSubmitted
|
1626
1708
|
: false,
|
1627
1709
|
dirtyFields: keepStateOptions.keepDirty
|
1628
1710
|
? _formState.dirtyFields
|
1629
|
-
:
|
1711
|
+
: (keepStateOptions.keepDefaultValues && formValues
|
1712
|
+
? Object.entries(formValues).reduce((previous, [key, value]) => (Object.assign(Object.assign({}, previous), { [key]: value !== get(_defaultValues, key) })), {})
|
1713
|
+
: {}),
|
1630
1714
|
touchedFields: keepStateOptions.keepTouched
|
1631
1715
|
? _formState.touchedFields
|
1632
1716
|
: {},
|
@@ -1640,11 +1724,15 @@ function createFormControl(props = {}) {
|
|
1640
1724
|
!_proxyFormState.isValid || !!keepStateOptions.keepIsValid;
|
1641
1725
|
_stateFlags.watch = !!props.shouldUnregister;
|
1642
1726
|
};
|
1643
|
-
const setFocus = (name) =>
|
1727
|
+
const setFocus = (name) => {
|
1728
|
+
const field = get(_fields, name)._f;
|
1729
|
+
(field.ref.focus ? field.ref : field.refs[0]).focus();
|
1730
|
+
};
|
1644
1731
|
return {
|
1645
1732
|
control: {
|
1646
1733
|
register,
|
1647
1734
|
unregister,
|
1735
|
+
_executeSchema,
|
1648
1736
|
_getWatch,
|
1649
1737
|
_getDirty,
|
1650
1738
|
_updateValid,
|
@@ -1703,6 +1791,7 @@ function createFormControl(props = {}) {
|
|
1703
1791
|
setValue,
|
1704
1792
|
getValues,
|
1705
1793
|
reset,
|
1794
|
+
resetField,
|
1706
1795
|
clearErrors,
|
1707
1796
|
unregister,
|
1708
1797
|
setError,
|
@@ -1751,42 +1840,10 @@ function useForm(props = {}) {
|
|
1751
1840
|
}
|
1752
1841
|
control._removeUnmounted();
|
1753
1842
|
});
|
1843
|
+
React.useEffect(() => () => Object.values(control._subjects).forEach((subject) => subject.unsubscribe()), [control]);
|
1754
1844
|
_formControl.current.formState = getProxyFormState(formState, control._proxyFormState);
|
1755
1845
|
return _formControl.current;
|
1756
1846
|
}
|
1757
1847
|
|
1758
|
-
function useWatch(props) {
|
1759
|
-
const methods = useFormContext();
|
1760
|
-
const { control = methods.control, name, defaultValue, disabled, } = props || {};
|
1761
|
-
const _name = React.useRef(name);
|
1762
|
-
_name.current = name;
|
1763
|
-
useSubscribe({
|
1764
|
-
disabled,
|
1765
|
-
subject: control._subjects.watch,
|
1766
|
-
callback: ({ name }) => {
|
1767
|
-
if (!_name.current ||
|
1768
|
-
!name ||
|
1769
|
-
convertToArrayPayload(_name.current).some((currentName) => name &&
|
1770
|
-
currentName &&
|
1771
|
-
(name.startsWith(currentName) ||
|
1772
|
-
currentName.startsWith(name)))) {
|
1773
|
-
control._stateFlags.mount = true;
|
1774
|
-
const fieldValues = control._getWatch(_name.current, defaultValue);
|
1775
|
-
updateValue(isObject(fieldValues)
|
1776
|
-
? Object.assign({}, fieldValues) : Array.isArray(fieldValues)
|
1777
|
-
? [...fieldValues]
|
1778
|
-
: fieldValues);
|
1779
|
-
}
|
1780
|
-
},
|
1781
|
-
});
|
1782
|
-
const [value, updateValue] = React.useState(isUndefined(defaultValue)
|
1783
|
-
? control._getWatch(name)
|
1784
|
-
: defaultValue);
|
1785
|
-
React.useEffect(() => {
|
1786
|
-
control._removeUnmounted();
|
1787
|
-
});
|
1788
|
-
return value;
|
1789
|
-
}
|
1790
|
-
|
1791
1848
|
export { Controller, FormProvider, appendErrors, get, set, useController, useFieldArray, useForm, useFormContext, useFormState, useWatch };
|
1792
1849
|
//# sourceMappingURL=index.esm.js.map
|