react-hook-form 7.12.1-next.0 → 7.12.1

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/dist/index.esm.js CHANGED
@@ -70,46 +70,50 @@ FormContext.displayName = 'RHFContext';
70
70
  const useFormContext = () => React.useContext(FormContext);
71
71
  const FormProvider = (props) => (React.createElement(FormContext.Provider, { value: omit(props, 'children') }, props.children));
72
72
 
73
- var getProxyFormState = (formState, _proxyFormState, localProxyFormState, isRoot = true) => {
74
- function createGetter(prop) {
75
- return () => {
76
- if (prop in formState) {
77
- if (_proxyFormState[prop] !== VALIDATION_MODE.all) {
78
- _proxyFormState[prop] = !isRoot || VALIDATION_MODE.all;
73
+ var getProxyFormState = (isProxyEnabled, formState, readFormStateRef, localReadFormStateRef, isRoot = true) => isProxyEnabled
74
+ ? new Proxy(formState, {
75
+ get: (obj, prop) => {
76
+ if (prop in obj) {
77
+ if (readFormStateRef.current[prop] !== VALIDATION_MODE.all) {
78
+ readFormStateRef.current[prop] = isRoot
79
+ ? VALIDATION_MODE.all
80
+ : true;
79
81
  }
80
- localProxyFormState && (localProxyFormState[prop] = true);
81
- return formState[prop];
82
+ localReadFormStateRef &&
83
+ (localReadFormStateRef.current[prop] = true);
84
+ return obj[prop];
82
85
  }
83
86
  return undefined;
84
- };
85
- }
86
- const result = {};
87
- for (const key in formState) {
88
- Object.defineProperty(result, key, {
89
- get: createGetter(key),
90
- });
91
- }
92
- return result;
93
- };
87
+ },
88
+ })
89
+ : formState;
94
90
 
95
91
  var isEmptyObject = (value) => isObject(value) && !Object.keys(value).length;
96
92
 
97
- var shouldRenderFormState = (formStateData, _proxyFormState, isRoot) => {
93
+ var shouldRenderFormState = (formStateData, readFormStateRef, isRoot) => {
98
94
  const formState = omit(formStateData, 'name');
99
95
  return (isEmptyObject(formState) ||
100
- Object.keys(formState).length >= Object.keys(_proxyFormState).length ||
101
- Object.keys(formState).find((key) => _proxyFormState[key] ===
102
- (!isRoot || VALIDATION_MODE.all)));
96
+ Object.keys(formState).length >= Object.keys(readFormStateRef).length ||
97
+ Object.keys(formState).find((key) => readFormStateRef[key] ===
98
+ (isRoot ? VALIDATION_MODE.all : true)));
103
99
  };
104
100
 
105
101
  var convertToArrayPayload = (value) => Array.isArray(value) ? value : [value];
106
102
 
103
+ var isWeb = typeof window !== 'undefined' &&
104
+ typeof window.HTMLElement !== 'undefined' &&
105
+ typeof document !== 'undefined';
106
+
107
+ const isProxyEnabled = isWeb ? 'Proxy' in window : typeof Proxy !== 'undefined';
108
+
107
109
  function useFormState(props) {
110
+ const { control, name } = props || {};
108
111
  const methods = useFormContext();
109
- const { control = methods.control, disabled, name } = props || {};
112
+ const { formStateRef, subjectsRef, readFormStateRef } = control || methods.control;
110
113
  const nameRef = React.useRef(name);
111
- const [formState, updateFormState] = React.useState(control._formState.val);
112
- const _localProxyFormState = React.useRef({
114
+ nameRef.current = name;
115
+ const [formState, updateFormState] = React.useState(formStateRef.current);
116
+ const readFormState = React.useRef({
113
117
  isDirty: false,
114
118
  dirtyFields: false,
115
119
  touchedFields: false,
@@ -117,61 +121,64 @@ function useFormState(props) {
117
121
  isValid: false,
118
122
  errors: false,
119
123
  });
120
- nameRef.current = name;
121
124
  React.useEffect(() => {
122
- const formStateSubscription = control._subjects.state.subscribe({
125
+ const formStateSubscription = subjectsRef.current.state.subscribe({
123
126
  next: (formState) => (!nameRef.current ||
124
127
  !formState.name ||
125
128
  convertToArrayPayload(nameRef.current).includes(formState.name)) &&
126
- shouldRenderFormState(formState, _localProxyFormState.current) &&
127
- updateFormState(Object.assign(Object.assign({}, control._formState.val), formState)),
129
+ shouldRenderFormState(formState, readFormState.current) &&
130
+ updateFormState(Object.assign(Object.assign({}, formStateRef.current), formState)),
128
131
  });
129
- disabled && formStateSubscription.unsubscribe();
130
132
  return () => formStateSubscription.unsubscribe();
131
- }, [disabled, control]);
132
- return getProxyFormState(formState, control._proxyFormState, _localProxyFormState.current, false);
133
+ }, []);
134
+ return getProxyFormState(isProxyEnabled, formState, readFormStateRef, readFormState, false);
133
135
  }
134
136
 
135
- function useController(props) {
137
+ function useController({ name, rules, defaultValue, control, shouldUnregister, }) {
136
138
  const methods = useFormContext();
137
- const { name, control = methods.control, shouldUnregister } = props;
138
- const [value, setInputStateValue] = React.useState(get(control._formValues, name, get(control._defaultValues, name, props.defaultValue)));
139
+ const { defaultValuesRef, register, fieldsRef, unregister, namesRef, subjectsRef, shouldUnmount, inFieldArrayActionRef, } = control || methods.control;
140
+ const field = get(fieldsRef.current, name);
141
+ const [value, setInputStateValue] = React.useState(field && field._f && !isUndefined(field._f.value)
142
+ ? field._f.value
143
+ : isUndefined(get(defaultValuesRef.current, name))
144
+ ? defaultValue
145
+ : get(defaultValuesRef.current, name));
146
+ const { onChange, onBlur, ref } = register(name, Object.assign(Object.assign({}, rules), { value }));
139
147
  const formState = useFormState({
140
148
  control: control || methods.control,
141
149
  name,
142
150
  });
143
- const registerProps = control.register(name, Object.assign(Object.assign({}, props.rules), { value }));
151
+ function updateIsMounted(name, value) {
152
+ const field = get(fieldsRef.current, name);
153
+ if (field && field._f) {
154
+ field._f.mount = value;
155
+ }
156
+ }
144
157
  React.useEffect(() => {
145
- const controllerSubscription = control._subjects.control.subscribe({
158
+ const controllerSubscription = subjectsRef.current.control.subscribe({
146
159
  next: (data) => (!data.name || name === data.name) &&
147
160
  setInputStateValue(get(data.values, name)),
148
161
  });
149
- const field = get(control._fields, name);
150
- if (field) {
151
- field._f.mount = true;
152
- }
162
+ updateIsMounted(name, true);
153
163
  return () => {
154
164
  controllerSubscription.unsubscribe();
155
- const _shouldUnregisterField = control._shouldUnregister || shouldUnregister;
156
- if (isNameInFieldArray(control._names.array, name)
157
- ? _shouldUnregisterField && !control._isInAction.val
158
- : _shouldUnregisterField) {
159
- control.unregister(name);
165
+ const shouldUnmountField = shouldUnmount || shouldUnregister;
166
+ if (isNameInFieldArray(namesRef.current.array, name)
167
+ ? shouldUnmountField && !inFieldArrayActionRef.current
168
+ : shouldUnmountField) {
169
+ unregister(name);
160
170
  }
161
171
  else {
162
- const field = get(control._fields, name);
163
- if (field) {
164
- field._f.mount = false;
165
- }
172
+ updateIsMounted(name, false);
166
173
  }
167
174
  };
168
- }, [name, control, shouldUnregister]);
175
+ }, [name]);
169
176
  return {
170
177
  field: {
171
178
  onChange: (event) => {
172
179
  const value = getControllerValue(event);
173
180
  setInputStateValue(value);
174
- registerProps.onChange({
181
+ onChange({
175
182
  target: {
176
183
  value,
177
184
  name: name,
@@ -180,7 +187,7 @@ function useController(props) {
180
187
  });
181
188
  },
182
189
  onBlur: () => {
183
- registerProps.onBlur({
190
+ onBlur({
184
191
  target: {
185
192
  name: name,
186
193
  },
@@ -190,7 +197,7 @@ function useController(props) {
190
197
  name,
191
198
  value,
192
199
  ref: (elm) => elm &&
193
- registerProps.ref({
200
+ ref({
194
201
  focus: () => elm.focus && elm.focus(),
195
202
  setCustomValidity: (message) => elm.setCustomValidity(message),
196
203
  reportValidity: () => elm.reportValidity(),
@@ -260,9 +267,27 @@ const focusFieldBy = (fields, callback, fieldsNames) => {
260
267
  }
261
268
  };
262
269
 
263
- var getFocusFieldName = (name, index, options) => options && !options.shouldFocus
264
- ? options.focusName || `${name}.${options.focusIndex}.`
265
- : `${name}.${index}.`;
270
+ const getFieldsValues = (fieldsRef, output = {}) => {
271
+ for (const name in fieldsRef.current) {
272
+ const field = fieldsRef.current[name];
273
+ if (field && !isNullOrUndefined(output)) {
274
+ const _f = field._f;
275
+ const current = omit(field, '_f');
276
+ set(output, name, _f && _f.ref
277
+ ? _f.ref.disabled || (_f.refs && _f.refs.every((ref) => ref.disabled))
278
+ ? undefined
279
+ : _f.value
280
+ : Array.isArray(field)
281
+ ? []
282
+ : {});
283
+ current &&
284
+ getFieldsValues({
285
+ current,
286
+ }, output[name]);
287
+ }
288
+ }
289
+ return output;
290
+ };
266
291
 
267
292
  var generateId = () => {
268
293
  const d = typeof performance === 'undefined' ? Date.now() : performance.now() * 1000;
@@ -274,6 +299,80 @@ var generateId = () => {
274
299
 
275
300
  var mapIds = (values = [], keyName) => values.map((value) => (Object.assign({ [keyName]: (value && value[keyName]) || generateId() }, value)));
276
301
 
302
+ var isPrimitive = (value) => isNullOrUndefined(value) || !isObjectType(value);
303
+
304
+ function deepEqual(object1, object2, isErrorObject) {
305
+ if (isPrimitive(object1) ||
306
+ isPrimitive(object2) ||
307
+ isDateObject(object1) ||
308
+ isDateObject(object2)) {
309
+ return object1 === object2;
310
+ }
311
+ if (!React.isValidElement(object1)) {
312
+ const keys1 = Object.keys(object1);
313
+ const keys2 = Object.keys(object2);
314
+ if (keys1.length !== keys2.length) {
315
+ return false;
316
+ }
317
+ for (const key of keys1) {
318
+ const val1 = object1[key];
319
+ if (!(isErrorObject && key === 'ref')) {
320
+ const val2 = object2[key];
321
+ if ((isObject(val1) || Array.isArray(val1)) &&
322
+ (isObject(val2) || Array.isArray(val2))
323
+ ? !deepEqual(val1, val2, isErrorObject)
324
+ : val1 !== val2) {
325
+ return false;
326
+ }
327
+ }
328
+ }
329
+ }
330
+ return true;
331
+ }
332
+
333
+ function deepMerge(target, source) {
334
+ if (isPrimitive(target) || isPrimitive(source)) {
335
+ return source;
336
+ }
337
+ for (const key in source) {
338
+ const targetValue = target[key];
339
+ const sourceValue = source[key];
340
+ try {
341
+ target[key] =
342
+ (isObject(targetValue) && isObject(sourceValue)) ||
343
+ (Array.isArray(targetValue) && Array.isArray(sourceValue))
344
+ ? deepMerge(targetValue, sourceValue)
345
+ : sourceValue;
346
+ }
347
+ catch (_a) { }
348
+ }
349
+ return target;
350
+ }
351
+
352
+ function setDirtyFields(values, defaultValues, dirtyFields, parentNode, parentName) {
353
+ let index = -1;
354
+ while (++index < values.length) {
355
+ for (const key in values[index]) {
356
+ if (Array.isArray(values[index][key])) {
357
+ !dirtyFields[index] && (dirtyFields[index] = {});
358
+ dirtyFields[index][key] = [];
359
+ setDirtyFields(values[index][key], get(defaultValues[index] || {}, key, []), dirtyFields[index][key], dirtyFields[index], key);
360
+ }
361
+ else {
362
+ !isNullOrUndefined(defaultValues) &&
363
+ deepEqual(get(defaultValues[index] || {}, key), values[index][key])
364
+ ? set(dirtyFields[index] || {}, key)
365
+ : (dirtyFields[index] = Object.assign(Object.assign({}, dirtyFields[index]), { [key]: true }));
366
+ }
367
+ }
368
+ parentNode &&
369
+ !dirtyFields.length &&
370
+ delete parentNode[parentName];
371
+ }
372
+ return dirtyFields;
373
+ }
374
+ var setFieldArrayDirtyFields = (values, defaultValues, dirtyFields) => deepMerge(setDirtyFields(values, defaultValues, dirtyFields.slice(0, values.length)), setDirtyFields(defaultValues, values, dirtyFields.slice(0, values.length)));
375
+
277
376
  function append(data, value) {
278
377
  return [...convertToArrayPayload(data), ...convertToArrayPayload(value)];
279
378
  }
@@ -299,8 +398,6 @@ var moveArrayAt = (data, from, to) => {
299
398
  return [];
300
399
  };
301
400
 
302
- var omitKey = (fields, keyName) => fields.map((field = {}) => omit(field, keyName));
303
-
304
401
  function prepend(data, value) {
305
402
  return [...convertToArrayPayload(value), ...convertToArrayPayload(data)];
306
403
  }
@@ -363,247 +460,211 @@ function unset(object, path) {
363
460
  return object;
364
461
  }
365
462
 
366
- const useFieldArray = (props) => {
463
+ const useFieldArray = ({ control, name, keyName = 'id', shouldUnregister, }) => {
367
464
  const methods = useFormContext();
368
- const { control = methods.control, name, keyName = 'id', shouldUnregister, } = props;
369
- const _focusName = React.useRef('');
370
- const [fields, setFields] = React.useState(mapIds(control._getFieldArrayValue(name), keyName));
371
- control._names.array.add(name);
465
+ const focusNameRef = React.useRef('');
466
+ const isMountedRef = React.useRef(false);
467
+ const { getIsDirty, namesRef, fieldsRef, defaultValuesRef, formStateRef, subjectsRef, readFormStateRef, updateIsValid, fieldArrayDefaultValuesRef, unregister, shouldUnmount, inFieldArrayActionRef, setValues, register, } = control || methods.control;
468
+ const [fields, setFields] = React.useState(mapIds((get(fieldsRef.current, name) && isMountedRef.current
469
+ ? get(getFieldsValues(fieldsRef), name)
470
+ : get(fieldArrayDefaultValuesRef.current, getNodeParentName(name))
471
+ ? get(fieldArrayDefaultValuesRef.current, name)
472
+ : get(defaultValuesRef.current, name)) || [], keyName));
473
+ set(fieldArrayDefaultValuesRef.current, name, [...fields]);
474
+ namesRef.current.array.add(name);
475
+ const omitKey = (fields) => fields.map((field = {}) => omit(field, keyName));
476
+ const getCurrentFieldsValues = () => {
477
+ const values = get(getFieldsValues(fieldsRef), name, []);
478
+ return mapIds(get(fieldArrayDefaultValuesRef.current, name, []).map((item, index) => (Object.assign(Object.assign({}, item), values[index]))), keyName);
479
+ };
480
+ const getFocusFieldName = (index, options) => options && !options.shouldFocus
481
+ ? options.focusName || `${name}.${options.focusIndex}.`
482
+ : `${name}.${index}.`;
483
+ const setFieldsAndNotify = (fieldsValues = []) => setFields(mapIds(fieldsValues, keyName));
484
+ const cleanup = (ref) => !compact(get(ref, name, [])).length && unset(ref, name);
485
+ const batchStateUpdate = (method, args, updatedFieldArrayValues = [], shouldSet = true) => {
486
+ inFieldArrayActionRef.current = true;
487
+ if (get(fieldsRef.current, name)) {
488
+ const output = method(get(fieldsRef.current, name), args.argA, args.argB);
489
+ shouldSet && set(fieldsRef.current, name, output);
490
+ }
491
+ if (Array.isArray(get(formStateRef.current.errors, name))) {
492
+ const output = method(get(formStateRef.current.errors, name), args.argA, args.argB);
493
+ shouldSet && set(formStateRef.current.errors, name, output);
494
+ cleanup(formStateRef.current.errors);
495
+ }
496
+ if (readFormStateRef.current.touchedFields &&
497
+ get(formStateRef.current.touchedFields, name)) {
498
+ const output = method(get(formStateRef.current.touchedFields, name), args.argA, args.argB);
499
+ shouldSet && set(formStateRef.current.touchedFields, name, output);
500
+ cleanup(formStateRef.current.touchedFields);
501
+ }
502
+ if (readFormStateRef.current.dirtyFields ||
503
+ readFormStateRef.current.isDirty) {
504
+ set(formStateRef.current.dirtyFields, name, setFieldArrayDirtyFields(omitKey(updatedFieldArrayValues), get(defaultValuesRef.current, name, []), get(formStateRef.current.dirtyFields, name, [])));
505
+ updatedFieldArrayValues &&
506
+ set(formStateRef.current.dirtyFields, name, setFieldArrayDirtyFields(omitKey(updatedFieldArrayValues), get(defaultValuesRef.current, name, []), get(formStateRef.current.dirtyFields, name, [])));
507
+ cleanup(formStateRef.current.dirtyFields);
508
+ }
509
+ subjectsRef.current.state.next({
510
+ dirtyFields: formStateRef.current
511
+ .dirtyFields,
512
+ isDirty: getIsDirty(name, omitKey(updatedFieldArrayValues)),
513
+ errors: formStateRef.current.errors,
514
+ isValid: formStateRef.current.isValid,
515
+ });
516
+ };
517
+ const registerFieldArray = (values, index = 0, parentName = '') => values.forEach((appendValueItem, valueIndex) => {
518
+ const rootName = `${parentName || name}.${parentName ? valueIndex : index + valueIndex}`;
519
+ isPrimitive(appendValueItem)
520
+ ? register(rootName, {
521
+ value: appendValueItem,
522
+ })
523
+ : Object.entries(appendValueItem).forEach(([key, value]) => {
524
+ const inputName = rootName + '.' + key;
525
+ Array.isArray(value)
526
+ ? registerFieldArray(value, valueIndex, inputName)
527
+ : register(inputName, { value });
528
+ });
529
+ });
372
530
  const append$1 = (value, options) => {
373
531
  const appendValue = convertToArrayPayload(value);
374
- const updatedFieldArrayValues = append(control._getFieldArrayValue(name), appendValue);
375
- setFields(mapIds(updatedFieldArrayValues, keyName));
376
- control._bathFieldArrayUpdate(keyName, name, append, {
532
+ const updatedFieldArrayValues = append(getCurrentFieldsValues(), appendValue);
533
+ const currentIndex = updatedFieldArrayValues.length - appendValue.length;
534
+ setFieldsAndNotify(updatedFieldArrayValues);
535
+ batchStateUpdate(append, {
377
536
  argA: fillEmptyArray(value),
378
537
  }, updatedFieldArrayValues, false);
379
- _focusName.current = getFocusFieldName(name, updatedFieldArrayValues.length - appendValue.length, options);
538
+ registerFieldArray(appendValue, currentIndex);
539
+ focusNameRef.current = getFocusFieldName(currentIndex, options);
380
540
  };
381
541
  const prepend$1 = (value, options) => {
382
- const updatedFieldArrayValues = prepend(control._getFieldArrayValue(name), convertToArrayPayload(value));
383
- setFields(mapIds(updatedFieldArrayValues, keyName));
384
- control._bathFieldArrayUpdate(keyName, name, prepend, {
542
+ const prependValue = convertToArrayPayload(value);
543
+ const updatedFieldArrayValues = prepend(getCurrentFieldsValues(), prependValue);
544
+ setFieldsAndNotify(updatedFieldArrayValues);
545
+ batchStateUpdate(prepend, {
385
546
  argA: fillEmptyArray(value),
386
547
  }, updatedFieldArrayValues);
387
- _focusName.current = getFocusFieldName(name, 0, options);
548
+ registerFieldArray(prependValue);
549
+ focusNameRef.current = getFocusFieldName(0, options);
388
550
  };
389
551
  const remove = (index) => {
390
- const updatedFieldArrayValues = removeArrayAt(control._getFieldArrayValue(name), index);
391
- setFields(mapIds(updatedFieldArrayValues, keyName));
392
- control._bathFieldArrayUpdate(keyName, name, removeArrayAt, {
552
+ const updatedFieldArrayValues = removeArrayAt(getCurrentFieldsValues(), index);
553
+ setFieldsAndNotify(updatedFieldArrayValues);
554
+ batchStateUpdate(removeArrayAt, {
393
555
  argA: index,
394
556
  }, updatedFieldArrayValues);
395
557
  };
396
558
  const insert$1 = (index, value, options) => {
397
- const updatedFieldArrayValues = insert(control._getFieldArrayValue(name), index, convertToArrayPayload(value));
398
- setFields(mapIds(updatedFieldArrayValues, keyName));
399
- control._bathFieldArrayUpdate(keyName, name, insert, {
559
+ const insertValue = convertToArrayPayload(value);
560
+ const updatedFieldArrayValues = insert(getCurrentFieldsValues(), index, insertValue);
561
+ setFieldsAndNotify(updatedFieldArrayValues);
562
+ batchStateUpdate(insert, {
400
563
  argA: index,
401
564
  argB: fillEmptyArray(value),
402
565
  }, updatedFieldArrayValues);
403
- _focusName.current = getFocusFieldName(name, index, options);
566
+ registerFieldArray(insertValue, index);
567
+ focusNameRef.current = getFocusFieldName(index, options);
404
568
  };
405
569
  const swap = (indexA, indexB) => {
406
- const fieldValues = control._getFieldArrayValue(name);
570
+ const fieldValues = getCurrentFieldsValues();
407
571
  swapArrayAt(fieldValues, indexA, indexB);
408
- control._bathFieldArrayUpdate(keyName, name, swapArrayAt, {
572
+ batchStateUpdate(swapArrayAt, {
409
573
  argA: indexA,
410
574
  argB: indexB,
411
575
  }, fieldValues, false);
412
- setFields(mapIds(fieldValues, keyName));
576
+ setFieldsAndNotify(fieldValues);
413
577
  };
414
578
  const move = (from, to) => {
415
- const fieldValues = control._getFieldArrayValue(name);
579
+ const fieldValues = getCurrentFieldsValues();
416
580
  moveArrayAt(fieldValues, from, to);
417
- setFields(mapIds(fieldValues, keyName));
418
- control._bathFieldArrayUpdate(keyName, name, moveArrayAt, {
581
+ setFieldsAndNotify(fieldValues);
582
+ batchStateUpdate(moveArrayAt, {
419
583
  argA: from,
420
584
  argB: to,
421
585
  }, fieldValues, false);
422
586
  };
423
587
  const update = (index, value) => {
424
- control._setValues((name + '.' + index), value, {
425
- shouldValidate: !!control._proxyFormState.isValid,
426
- shouldDirty: !!(control._proxyFormState.dirtyFields || control._proxyFormState.isDirty),
588
+ setValues((name + '.' + index), value, {
589
+ shouldValidate: !!readFormStateRef.current.isValid,
590
+ shouldDirty: !!(readFormStateRef.current.dirtyFields ||
591
+ readFormStateRef.current.isDirty),
427
592
  });
428
- const fieldValues = control._getFieldArrayValue(name);
593
+ const fieldValues = getCurrentFieldsValues();
429
594
  fieldValues[index] = value;
430
- setFields(mapIds(fieldValues, keyName));
595
+ setFieldsAndNotify(fieldValues);
431
596
  };
432
597
  React.useEffect(() => {
433
- control._isInAction.val = false;
434
- if (control._names.watchAll) {
435
- control._subjects.state.next({});
598
+ inFieldArrayActionRef.current = false;
599
+ if (namesRef.current.watchAll) {
600
+ subjectsRef.current.state.next({});
436
601
  }
437
602
  else {
438
- for (const watchField of control._names.watch) {
603
+ for (const watchField of namesRef.current.watch) {
439
604
  if (name.startsWith(watchField)) {
440
- control._subjects.state.next({});
605
+ subjectsRef.current.state.next({});
441
606
  break;
442
607
  }
443
608
  }
444
609
  }
445
- control._subjects.watch.next({
610
+ subjectsRef.current.watch.next({
446
611
  name,
447
- values: control._formValues,
612
+ values: getFieldsValues(fieldsRef),
448
613
  });
449
- _focusName.current &&
450
- focusFieldBy(control._fields, (key) => key.startsWith(_focusName.current));
451
- _focusName.current = '';
452
- control._subjects.array.next({
614
+ focusNameRef.current &&
615
+ focusFieldBy(fieldsRef.current, (key) => key.startsWith(focusNameRef.current));
616
+ focusNameRef.current = '';
617
+ subjectsRef.current.array.next({
453
618
  name,
454
- values: omitKey([...fields], keyName),
619
+ values: omitKey([...fields]),
455
620
  });
456
- control._proxyFormState.isValid && control._updateValid();
457
- }, [fields, name, control, keyName]);
621
+ readFormStateRef.current.isValid && updateIsValid();
622
+ }, [fields, name]);
458
623
  React.useEffect(() => {
459
- const fieldArraySubscription = control._subjects.array.subscribe({
460
- next(payload) {
461
- if (payload.isReset) {
462
- unset(control._fields, payload.name || name);
463
- unset(control._formValues, payload.name || name);
464
- payload.name
465
- ? set(control._formValues, payload.name, payload.values)
466
- : payload.values && (control._formValues = payload.values);
467
- setFields(mapIds(get(control._formValues, name), keyName));
624
+ const fieldArraySubscription = subjectsRef.current.array.subscribe({
625
+ next({ name: inputFieldArrayName, values, isReset }) {
626
+ if (isReset) {
627
+ unset(fieldsRef.current, inputFieldArrayName || name);
628
+ inputFieldArrayName
629
+ ? set(fieldArrayDefaultValuesRef.current, inputFieldArrayName, values)
630
+ : (fieldArrayDefaultValuesRef.current = values);
631
+ setFieldsAndNotify(get(fieldArrayDefaultValuesRef.current, name));
468
632
  }
469
633
  },
470
634
  });
471
- !get(control._formValues, name) && set(control._formValues, name, []);
635
+ !get(fieldsRef.current, name) && set(fieldsRef.current, name, []);
636
+ isMountedRef.current = true;
472
637
  return () => {
473
638
  fieldArraySubscription.unsubscribe();
474
- if (control._shouldUnregister || shouldUnregister) {
475
- control.unregister(name);
476
- unset(control._formValues, name);
639
+ if (shouldUnmount || shouldUnregister) {
640
+ unregister(name);
641
+ unset(fieldArrayDefaultValuesRef.current, name);
477
642
  }
478
643
  else {
479
- const fieldArrayValues = get(control._formValues, name);
480
- fieldArrayValues && set(control._formValues, name, fieldArrayValues);
644
+ const fieldArrayValues = get(getFieldsValues(fieldsRef), name);
645
+ fieldArrayValues &&
646
+ set(fieldArrayDefaultValuesRef.current, name, fieldArrayValues);
481
647
  }
482
648
  };
483
- }, [name, control, keyName, shouldUnregister]);
649
+ }, []);
484
650
  return {
485
- swap: React.useCallback(swap, [name, control, keyName]),
486
- move: React.useCallback(move, [name, control, keyName]),
487
- prepend: React.useCallback(prepend$1, [name, control, keyName]),
488
- append: React.useCallback(append$1, [name, control, keyName]),
489
- remove: React.useCallback(remove, [name, control, keyName]),
490
- insert: React.useCallback(insert$1, [name, control, keyName]),
491
- update: React.useCallback(update, [name, control, keyName]),
651
+ swap: React.useCallback(swap, [name]),
652
+ move: React.useCallback(move, [name]),
653
+ prepend: React.useCallback(prepend$1, [name]),
654
+ append: React.useCallback(append$1, [name]),
655
+ remove: React.useCallback(remove, [name]),
656
+ insert: React.useCallback(insert$1, [name]),
657
+ update: React.useCallback(update, [name]),
492
658
  fields: fields,
493
659
  };
494
660
  };
495
661
 
496
- var debounce = (callback, wait) => {
497
- let timer = 0;
498
- return (...args) => {
499
- clearTimeout(timer);
500
- timer = setTimeout(() => callback(...args), wait);
501
- };
502
- };
503
-
504
- var isPrimitive = (value) => isNullOrUndefined(value) || !isObjectType(value);
505
-
506
- function deepEqual(object1, object2, isErrorObject) {
507
- if (isPrimitive(object1) ||
508
- isPrimitive(object2) ||
509
- isDateObject(object1) ||
510
- isDateObject(object2)) {
511
- return object1 === object2;
512
- }
513
- if (!React.isValidElement(object1)) {
514
- const keys1 = Object.keys(object1);
515
- const keys2 = Object.keys(object2);
516
- if (keys1.length !== keys2.length) {
517
- return false;
518
- }
519
- for (const key of keys1) {
520
- const val1 = object1[key];
521
- if (!(isErrorObject && key === 'ref')) {
522
- const val2 = object2[key];
523
- if ((isObject(val1) || Array.isArray(val1)) &&
524
- (isObject(val2) || Array.isArray(val2))
525
- ? !deepEqual(val1, val2, isErrorObject)
526
- : val1 !== val2) {
527
- return false;
528
- }
529
- }
530
- }
531
- }
532
- return true;
533
- }
534
-
535
- var getValidationModes = (mode) => ({
536
- isOnSubmit: !mode || mode === VALIDATION_MODE.onSubmit,
537
- isOnBlur: mode === VALIDATION_MODE.onBlur,
538
- isOnChange: mode === VALIDATION_MODE.onChange,
539
- isOnAll: mode === VALIDATION_MODE.all,
540
- isOnTouch: mode === VALIDATION_MODE.onTouched,
541
- });
542
-
543
662
  var isFileInput = (element) => element.type === 'file';
544
663
 
545
- var isFunction = (value) => typeof value === 'function';
546
-
547
- var isHTMLElement = (value) => value instanceof HTMLElement;
548
-
549
664
  var isMultipleSelect = (element) => element.type === `select-multiple`;
550
665
 
551
666
  var isRadioInput = (element) => element.type === 'radio';
552
667
 
553
- var isRadioOrCheckboxFunction = (ref) => isRadioInput(ref) || isCheckBoxInput(ref);
554
-
555
- var isString = (value) => typeof value === 'string';
556
-
557
- var isWeb = typeof window !== 'undefined' &&
558
- typeof window.HTMLElement !== 'undefined' &&
559
- typeof document !== 'undefined';
560
-
561
- class Subscription {
562
- constructor() {
563
- this.tearDowns = [];
564
- }
565
- add(tearDown) {
566
- this.tearDowns.push(tearDown);
567
- }
568
- unsubscribe() {
569
- for (const teardown of this.tearDowns) {
570
- teardown();
571
- }
572
- this.tearDowns = [];
573
- }
574
- }
575
- class Subscriber {
576
- constructor(observer, subscription) {
577
- this.observer = observer;
578
- this.closed = false;
579
- subscription.add(() => (this.closed = true));
580
- }
581
- next(value) {
582
- if (!this.closed) {
583
- this.observer.next(value);
584
- }
585
- }
586
- }
587
- class Subject {
588
- constructor() {
589
- this.observers = [];
590
- }
591
- next(value) {
592
- for (const observer of this.observers) {
593
- observer.next(value);
594
- }
595
- }
596
- subscribe(observer) {
597
- const subscription = new Subscription();
598
- const subscriber = new Subscriber(observer, subscription);
599
- this.observers.push(subscriber);
600
- return subscription;
601
- }
602
- unsubscribe() {
603
- this.observers = [];
604
- }
605
- }
606
-
607
668
  const defaultResult = {
608
669
  value: false,
609
670
  isValid: false,
@@ -661,7 +722,7 @@ var getRadioValue = (options) => Array.isArray(options)
661
722
  function getFieldValue(field) {
662
723
  if (field && field._f) {
663
724
  const ref = field._f.ref;
664
- if (field._f.refs ? field._f.refs.every((ref) => ref.disabled) : ref.disabled) {
725
+ if (ref.disabled) {
665
726
  return;
666
727
  }
667
728
  if (isFileInput(ref)) {
@@ -680,10 +741,10 @@ function getFieldValue(field) {
680
741
  }
681
742
  }
682
743
 
683
- var getResolverOptions = (fieldsNames, _fieldss, criteriaMode, shouldUseNativeValidation) => {
744
+ var getResolverOptions = (fieldsNames, fieldsRefs, criteriaMode, shouldUseNativeValidation) => {
684
745
  const fields = {};
685
746
  for (const name of fieldsNames) {
686
- const field = get(_fieldss, name);
747
+ const field = get(fieldsRefs, name);
687
748
  field && set(fields, name, field._f);
688
749
  }
689
750
  return {
@@ -704,49 +765,6 @@ var hasValidation = (options, mounted) => mounted &&
704
765
  options.pattern ||
705
766
  options.validate);
706
767
 
707
- function deepMerge(target, source) {
708
- if (isPrimitive(target) || isPrimitive(source)) {
709
- return source;
710
- }
711
- for (const key in source) {
712
- const targetValue = target[key];
713
- const sourceValue = source[key];
714
- try {
715
- target[key] =
716
- (isObject(targetValue) && isObject(sourceValue)) ||
717
- (Array.isArray(targetValue) && Array.isArray(sourceValue))
718
- ? deepMerge(targetValue, sourceValue)
719
- : sourceValue;
720
- }
721
- catch (_a) { }
722
- }
723
- return target;
724
- }
725
-
726
- function setDirtyFields(values, defaultValues, dirtyFields, parentNode, parentName) {
727
- let index = -1;
728
- while (++index < values.length) {
729
- for (const key in values[index]) {
730
- if (Array.isArray(values[index][key])) {
731
- !dirtyFields[index] && (dirtyFields[index] = {});
732
- dirtyFields[index][key] = [];
733
- setDirtyFields(values[index][key], get(defaultValues[index] || {}, key, []), dirtyFields[index][key], dirtyFields[index], key);
734
- }
735
- else {
736
- !isNullOrUndefined(defaultValues) &&
737
- deepEqual(get(defaultValues[index] || {}, key), values[index][key])
738
- ? set(dirtyFields[index] || {}, key)
739
- : (dirtyFields[index] = Object.assign(Object.assign({}, dirtyFields[index]), { [key]: true }));
740
- }
741
- }
742
- parentNode &&
743
- !dirtyFields.length &&
744
- delete parentNode[parentName];
745
- }
746
- return dirtyFields;
747
- }
748
- var setFieldArrayDirtyFields = (values, defaultValues, dirtyFields) => deepMerge(setDirtyFields(values, defaultValues, dirtyFields.slice(0, values.length)), setDirtyFields(defaultValues, values, dirtyFields.slice(0, values.length)));
749
-
750
768
  var skipValidation = ({ isOnBlur, isOnChange, isOnTouch, isTouched, isReValidateOnBlur, isReValidateOnChange, isBlurEvent, isSubmitted, isOnAll, }) => {
751
769
  if (isOnAll) {
752
770
  return false;
@@ -763,7 +781,9 @@ var skipValidation = ({ isOnBlur, isOnChange, isOnTouch, isTouched, isReValidate
763
781
  return true;
764
782
  };
765
783
 
766
- var unsetEmptyArray = (ref, name) => !compact(get(ref, name, [])).length && unset(ref, name);
784
+ var isFunction = (value) => typeof value === 'function';
785
+
786
+ var isString = (value) => typeof value === 'string';
767
787
 
768
788
  var isMessage = (value) => isString(value) || React.isValidElement(value);
769
789
 
@@ -788,8 +808,7 @@ var getValueAndMessage = (validationData) => isObject(validationData) && !isRege
788
808
  message: '',
789
809
  };
790
810
 
791
- var validateField = async (field, inputValue, validateAllFieldCriteria, shouldUseNativeValidation) => {
792
- const { ref, refs, required, maxLength, minLength, min, max, pattern, validate, name, valueAsNumber, mount, } = field._f;
811
+ var validateField = async ({ _f: { ref, refs, required, maxLength, minLength, min, max, pattern, validate, name, value: inputValue, valueAsNumber, mount, }, }, validateAllFieldCriteria, shouldUseNativeValidation) => {
793
812
  if (!mount) {
794
813
  return {};
795
814
  }
@@ -925,16 +944,75 @@ var validateField = async (field, inputValue, validateAllFieldCriteria, shouldUs
925
944
  return error;
926
945
  };
927
946
 
928
- const defaultOptions = {
929
- mode: VALIDATION_MODE.onSubmit,
930
- reValidateMode: VALIDATION_MODE.onChange,
931
- shouldFocusError: true,
932
- };
947
+ var debounce = (callback, wait) => {
948
+ let timer = 0;
949
+ return (...args) => {
950
+ clearTimeout(timer);
951
+ timer = setTimeout(() => callback(...args), wait);
952
+ };
953
+ };
954
+
955
+ var getValidationModes = (mode) => ({
956
+ isOnSubmit: !mode || mode === VALIDATION_MODE.onSubmit,
957
+ isOnBlur: mode === VALIDATION_MODE.onBlur,
958
+ isOnChange: mode === VALIDATION_MODE.onChange,
959
+ isOnAll: mode === VALIDATION_MODE.all,
960
+ isOnTouch: mode === VALIDATION_MODE.onTouched,
961
+ });
962
+
963
+ var isHTMLElement = (value) => value instanceof HTMLElement;
964
+
965
+ var isRadioOrCheckboxFunction = (ref) => isRadioInput(ref) || isCheckBoxInput(ref);
966
+
967
+ class Subscription {
968
+ constructor() {
969
+ this.tearDowns = [];
970
+ }
971
+ add(tearDown) {
972
+ this.tearDowns.push(tearDown);
973
+ }
974
+ unsubscribe() {
975
+ for (const teardown of this.tearDowns) {
976
+ teardown();
977
+ }
978
+ this.tearDowns = [];
979
+ }
980
+ }
981
+ class Subscriber {
982
+ constructor(observer, subscription) {
983
+ this.observer = observer;
984
+ this.closed = false;
985
+ subscription.add(() => (this.closed = true));
986
+ }
987
+ next(value) {
988
+ if (!this.closed) {
989
+ this.observer.next(value);
990
+ }
991
+ }
992
+ }
993
+ class Subject {
994
+ constructor() {
995
+ this.observers = [];
996
+ }
997
+ next(value) {
998
+ for (const observer of this.observers) {
999
+ observer.next(value);
1000
+ }
1001
+ }
1002
+ subscribe(observer) {
1003
+ const subscription = new Subscription();
1004
+ const subscriber = new Subscriber(observer, subscription);
1005
+ this.observers.push(subscriber);
1006
+ return subscription;
1007
+ }
1008
+ unsubscribe() {
1009
+ this.observers = [];
1010
+ }
1011
+ }
1012
+
933
1013
  const isWindowUndefined = typeof window === 'undefined';
934
- function createFormControl(props = {}) {
935
- let formOptions = Object.assign(Object.assign({}, defaultOptions), props);
936
- let _delayCallback;
937
- let _formState = {
1014
+ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_MODE.onChange, resolver, context, defaultValues = {}, shouldFocusError = true, delayError, shouldUseNativeValidation, shouldUnregister, criteriaMode, } = {}) {
1015
+ const [formState, updateFormState] = React.useState({
938
1016
  isDirty: false,
939
1017
  isValidating: false,
940
1018
  dirtyFields: {},
@@ -945,172 +1023,201 @@ function createFormControl(props = {}) {
945
1023
  isSubmitSuccessful: false,
946
1024
  isValid: false,
947
1025
  errors: {},
948
- };
949
- const _proxyFormState = {
950
- isDirty: false,
951
- dirtyFields: false,
952
- touchedFields: false,
953
- isValidating: false,
954
- isValid: false,
955
- errors: false,
956
- };
957
- let _fields = {};
958
- let _formValues = {};
959
- let _defaultValues = formOptions.defaultValues || {};
960
- let _isInAction = false;
961
- let _isMounted = false;
962
- const _subjects = {
1026
+ });
1027
+ const readFormStateRef = React.useRef({
1028
+ isDirty: !isProxyEnabled,
1029
+ dirtyFields: !isProxyEnabled,
1030
+ touchedFields: !isProxyEnabled,
1031
+ isValidating: !isProxyEnabled,
1032
+ isValid: !isProxyEnabled,
1033
+ errors: !isProxyEnabled,
1034
+ });
1035
+ const resolverRef = React.useRef(resolver);
1036
+ const formStateRef = React.useRef(formState);
1037
+ const fieldsRef = React.useRef({});
1038
+ const defaultValuesRef = React.useRef(defaultValues);
1039
+ const fieldArrayDefaultValuesRef = React.useRef({});
1040
+ const contextRef = React.useRef(context);
1041
+ const inFieldArrayActionRef = React.useRef(false);
1042
+ const isMountedRef = React.useRef(false);
1043
+ const _delayCallback = React.useRef();
1044
+ const subjectsRef = React.useRef({
963
1045
  watch: new Subject(),
964
1046
  control: new Subject(),
965
1047
  array: new Subject(),
966
1048
  state: new Subject(),
967
- };
968
- let _names = {
1049
+ });
1050
+ const namesRef = React.useRef({
969
1051
  mount: new Set(),
970
1052
  unMount: new Set(),
971
1053
  array: new Set(),
972
1054
  watch: new Set(),
973
1055
  watchAll: false,
1056
+ });
1057
+ const validationMode = getValidationModes(mode);
1058
+ const isValidateAllFieldCriteria = criteriaMode === VALIDATION_MODE.all;
1059
+ resolverRef.current = resolver;
1060
+ contextRef.current = context;
1061
+ const isFieldWatched = (name) => namesRef.current.watchAll ||
1062
+ namesRef.current.watch.has(name) ||
1063
+ namesRef.current.watch.has((name.match(/\w+/) || [])[0]);
1064
+ const updateErrorState = (name, error) => {
1065
+ set(formStateRef.current.errors, name, error);
1066
+ subjectsRef.current.state.next({
1067
+ errors: formStateRef.current.errors,
1068
+ });
974
1069
  };
975
- const validationMode = getValidationModes(formOptions.mode);
976
- const isValidateAllFieldCriteria = formOptions.criteriaMode === VALIDATION_MODE.all;
977
- const isFieldWatched = (name) => _names.watchAll ||
978
- _names.watch.has(name) ||
979
- _names.watch.has((name.match(/\w+/) || [])[0]);
980
- const shouldRenderBaseOnError = async (shouldSkipRender, name, error, fieldState, isValidFromResolver, isWatched) => {
981
- const previousError = get(_formState.errors, name);
982
- const isValid = _proxyFormState.isValid
983
- ? formOptions.resolver
1070
+ const shouldRenderBaseOnError = React.useCallback(async (shouldSkipRender, name, error, fieldState, isValidFromResolver, isWatched) => {
1071
+ const previousError = get(formStateRef.current.errors, name);
1072
+ const isValid = readFormStateRef.current.isValid
1073
+ ? resolver
984
1074
  ? isValidFromResolver
985
- : await validateForm(_fields, true)
1075
+ : await validateForm(fieldsRef.current, true)
986
1076
  : false;
987
- error
988
- ? set(_formState.errors, name, error)
989
- : unset(_formState.errors, name);
1077
+ if (delayError && error) {
1078
+ _delayCallback.current =
1079
+ _delayCallback.current || debounce(updateErrorState, delayError);
1080
+ _delayCallback.current(name, error);
1081
+ }
1082
+ else {
1083
+ error
1084
+ ? set(formStateRef.current.errors, name, error)
1085
+ : unset(formStateRef.current.errors, name);
1086
+ }
990
1087
  if ((isWatched ||
991
1088
  (error ? !deepEqual(previousError, error, true) : previousError) ||
992
1089
  !isEmptyObject(fieldState) ||
993
- _formState.isValid !== isValid) &&
1090
+ formStateRef.current.isValid !== isValid) &&
994
1091
  !shouldSkipRender) {
995
- const updatedFormState = Object.assign(Object.assign({}, fieldState), { isValid: !!isValid, errors: _formState.errors, name });
996
- _formState = Object.assign(Object.assign({}, _formState), updatedFormState);
997
- _subjects.state.next(isWatched ? { name } : updatedFormState);
1092
+ const updatedFormState = Object.assign(Object.assign({}, fieldState), { isValid: !!isValid, errors: formStateRef.current.errors, name });
1093
+ formStateRef.current = Object.assign(Object.assign({}, formStateRef.current), updatedFormState);
1094
+ subjectsRef.current.state.next(isWatched ? { name } : updatedFormState);
998
1095
  }
999
- _subjects.state.next({
1096
+ subjectsRef.current.state.next({
1000
1097
  isValidating: false,
1001
1098
  });
1002
- };
1003
- const setFieldValue = (name, value, options = {}, shouldRender, shouldRegister) => {
1099
+ }, []);
1100
+ const setFieldValue = React.useCallback((name, rawValue, options = {}, shouldRender, shouldRegister) => {
1004
1101
  shouldRegister && register(name);
1005
- const field = get(_fields, name);
1102
+ const field = get(fieldsRef.current, name);
1006
1103
  if (field) {
1007
1104
  const _f = field._f;
1008
1105
  if (_f) {
1009
- set(_formValues, name, getFieldValueAs(value, _f));
1010
- const fieldValue = isWeb && isHTMLElement(_f.ref) && isNullOrUndefined(value)
1106
+ const value = isWeb && isHTMLElement(_f.ref) && isNullOrUndefined(rawValue)
1011
1107
  ? ''
1012
- : value;
1013
- if (isFileInput(_f.ref) && !isString(fieldValue)) {
1014
- _f.ref.files = fieldValue;
1108
+ : rawValue;
1109
+ _f.value = getFieldValueAs(rawValue, _f);
1110
+ if (isRadioInput(_f.ref)) {
1111
+ (_f.refs || []).forEach((radioRef) => (radioRef.checked = radioRef.value === value));
1112
+ }
1113
+ else if (isFileInput(_f.ref) && !isString(value)) {
1114
+ _f.ref.files = value;
1015
1115
  }
1016
1116
  else if (isMultipleSelect(_f.ref)) {
1017
- [..._f.ref.options].forEach((selectRef) => (selectRef.selected = fieldValue.includes(selectRef.value)));
1117
+ [..._f.ref.options].forEach((selectRef) => (selectRef.selected = value.includes(selectRef.value)));
1018
1118
  }
1019
- else if (_f.refs) {
1020
- if (isCheckBoxInput(_f.ref)) {
1021
- _f.refs.length > 1
1022
- ? _f.refs.forEach((checkboxRef) => (checkboxRef.checked = Array.isArray(fieldValue)
1023
- ? !!fieldValue.find((data) => data === checkboxRef.value)
1024
- : fieldValue === checkboxRef.value))
1025
- : (_f.refs[0].checked = !!fieldValue);
1026
- }
1027
- else {
1028
- _f.refs.forEach((radioRef) => (radioRef.checked = radioRef.value === fieldValue));
1029
- }
1119
+ else if (isCheckBoxInput(_f.ref) && _f.refs) {
1120
+ _f.refs.length > 1
1121
+ ? _f.refs.forEach((checkboxRef) => (checkboxRef.checked = Array.isArray(value)
1122
+ ? !!value.find((data) => data === checkboxRef.value)
1123
+ : value === checkboxRef.value))
1124
+ : (_f.refs[0].checked = !!value);
1030
1125
  }
1031
1126
  else {
1032
- _f.ref.value = fieldValue;
1127
+ _f.ref.value = value;
1033
1128
  }
1034
1129
  if (shouldRender) {
1035
- _subjects.control.next({
1036
- values: getValues(),
1130
+ const values = getFieldsValues(fieldsRef);
1131
+ set(values, name, rawValue);
1132
+ subjectsRef.current.control.next({
1133
+ values: Object.assign(Object.assign({}, defaultValuesRef.current), values),
1037
1134
  name,
1038
1135
  });
1039
1136
  }
1040
1137
  (options.shouldDirty || options.shouldTouch) &&
1041
- updateTouchAndDirtyState(name, fieldValue, options.shouldTouch);
1138
+ updateTouchAndDirtyState(name, value, options.shouldTouch);
1042
1139
  options.shouldValidate && trigger(name);
1043
1140
  }
1141
+ else {
1142
+ field._f = {
1143
+ ref: {
1144
+ name,
1145
+ value: rawValue,
1146
+ },
1147
+ value: rawValue,
1148
+ };
1149
+ }
1044
1150
  }
1045
- };
1046
- const updateTouchAndDirtyState = (name, inputValue, isCurrentTouched, shouldRender = true) => {
1151
+ }, []);
1152
+ const getIsDirty = React.useCallback((name, data) => {
1153
+ const formValues = getFieldsValues(fieldsRef);
1154
+ name && data && set(formValues, name, data);
1155
+ return !deepEqual(formValues, defaultValuesRef.current);
1156
+ }, []);
1157
+ const updateTouchAndDirtyState = React.useCallback((name, inputValue, isCurrentTouched, shouldRender = true) => {
1047
1158
  const state = {
1048
1159
  name,
1049
1160
  };
1050
1161
  let isChanged = false;
1051
- if (_proxyFormState.isDirty) {
1052
- const previousIsDirty = _formState.isDirty;
1053
- _formState.isDirty = _getIsDirty();
1054
- state.isDirty = _formState.isDirty;
1162
+ if (readFormStateRef.current.isDirty) {
1163
+ const previousIsDirty = formStateRef.current.isDirty;
1164
+ formStateRef.current.isDirty = getIsDirty();
1165
+ state.isDirty = formStateRef.current.isDirty;
1055
1166
  isChanged = previousIsDirty !== state.isDirty;
1056
1167
  }
1057
- if (_proxyFormState.dirtyFields && !isCurrentTouched) {
1058
- const isPreviousFieldDirty = get(_formState.dirtyFields, name);
1059
- const isCurrentFieldDirty = !deepEqual(get(_defaultValues, name), inputValue);
1168
+ if (readFormStateRef.current.dirtyFields && !isCurrentTouched) {
1169
+ const isPreviousFieldDirty = get(formStateRef.current.dirtyFields, name);
1170
+ const isCurrentFieldDirty = !deepEqual(get(defaultValuesRef.current, name), inputValue);
1060
1171
  isCurrentFieldDirty
1061
- ? set(_formState.dirtyFields, name, true)
1062
- : unset(_formState.dirtyFields, name);
1063
- state.dirtyFields = _formState.dirtyFields;
1172
+ ? set(formStateRef.current.dirtyFields, name, true)
1173
+ : unset(formStateRef.current.dirtyFields, name);
1174
+ state.dirtyFields = formStateRef.current.dirtyFields;
1064
1175
  isChanged =
1065
- isChanged || isPreviousFieldDirty !== get(_formState.dirtyFields, name);
1176
+ isChanged ||
1177
+ isPreviousFieldDirty !== get(formStateRef.current.dirtyFields, name);
1066
1178
  }
1067
- const isPreviousFieldTouched = get(_formState.touchedFields, name);
1179
+ const isPreviousFieldTouched = get(formStateRef.current.touchedFields, name);
1068
1180
  if (isCurrentTouched && !isPreviousFieldTouched) {
1069
- set(_formState.touchedFields, name, isCurrentTouched);
1070
- state.touchedFields = _formState.touchedFields;
1181
+ set(formStateRef.current.touchedFields, name, isCurrentTouched);
1182
+ state.touchedFields = formStateRef.current.touchedFields;
1071
1183
  isChanged =
1072
1184
  isChanged ||
1073
- (_proxyFormState.touchedFields &&
1185
+ (readFormStateRef.current.touchedFields &&
1074
1186
  isPreviousFieldTouched !== isCurrentTouched);
1075
1187
  }
1076
- isChanged && shouldRender && _subjects.state.next(state);
1188
+ isChanged && shouldRender && subjectsRef.current.state.next(state);
1077
1189
  return isChanged ? state : {};
1078
- };
1079
- const executeResolver = async (name) => {
1080
- return formOptions.resolver
1081
- ? await formOptions.resolver(Object.assign({}, _formValues), formOptions.context, getResolverOptions(name || _names.mount, _fields, formOptions.criteriaMode, formOptions.shouldUseNativeValidation))
1082
- : {};
1083
- };
1084
- const executeBuildinValidation = async (name, skipReRender) => {
1085
- const error = (await validateField(get(_fields, name), getValues(name), isValidateAllFieldCriteria, formOptions.shouldUseNativeValidation))[name];
1190
+ }, []);
1191
+ const executeInlineValidation = React.useCallback(async (name, skipReRender) => {
1192
+ const error = (await validateField(get(fieldsRef.current, name), isValidateAllFieldCriteria, shouldUseNativeValidation))[name];
1086
1193
  await shouldRenderBaseOnError(skipReRender, name, error);
1087
1194
  return isUndefined(error);
1088
- };
1089
- const executeResolverValidation = async (names) => {
1090
- const { errors } = await executeResolver();
1195
+ }, [isValidateAllFieldCriteria]);
1196
+ const executeResolverValidation = React.useCallback(async (names) => {
1197
+ const { errors } = await resolverRef.current(getFieldsValues(fieldsRef), contextRef.current, getResolverOptions(namesRef.current.mount, fieldsRef.current, criteriaMode, shouldUseNativeValidation));
1091
1198
  if (names) {
1092
1199
  for (const name of names) {
1093
1200
  const error = get(errors, name);
1094
1201
  error
1095
- ? set(_formState.errors, name, error)
1096
- : unset(_formState.errors, name);
1202
+ ? set(formStateRef.current.errors, name, error)
1203
+ : unset(formStateRef.current.errors, name);
1097
1204
  }
1098
1205
  }
1099
1206
  else {
1100
- _formState.errors = errors;
1207
+ formStateRef.current.errors = errors;
1101
1208
  }
1102
1209
  return errors;
1103
- };
1104
- const validateForm = async (_fields, shouldCheckValid, context = {
1210
+ }, [criteriaMode, shouldUseNativeValidation]);
1211
+ const validateForm = async (fieldsRef, shouldCheckValid, context = {
1105
1212
  valid: true,
1106
1213
  }) => {
1107
- for (const name in _fields) {
1108
- const field = _fields[name];
1214
+ for (const name in fieldsRef) {
1215
+ const field = fieldsRef[name];
1109
1216
  if (field) {
1110
1217
  const _f = field._f;
1111
- const val = omit(field, '_f');
1218
+ const current = omit(field, '_f');
1112
1219
  if (_f) {
1113
- const fieldError = await validateField(field, get(_formValues, _f.name), isValidateAllFieldCriteria, formOptions.shouldUseNativeValidation);
1220
+ const fieldError = await validateField(field, isValidateAllFieldCriteria, shouldUseNativeValidation);
1114
1221
  if (shouldCheckValid) {
1115
1222
  if (fieldError[_f.name]) {
1116
1223
  context.valid = false;
@@ -1119,254 +1226,185 @@ function createFormControl(props = {}) {
1119
1226
  }
1120
1227
  else {
1121
1228
  fieldError[_f.name]
1122
- ? set(_formState.errors, _f.name, fieldError[_f.name])
1123
- : unset(_formState.errors, _f.name);
1229
+ ? set(formStateRef.current.errors, _f.name, fieldError[_f.name])
1230
+ : unset(formStateRef.current.errors, _f.name);
1124
1231
  }
1125
1232
  }
1126
- val && (await validateForm(val, shouldCheckValid, context));
1233
+ current && (await validateForm(current, shouldCheckValid, context));
1127
1234
  }
1128
1235
  }
1129
1236
  return context.valid;
1130
1237
  };
1131
- const handleValidate = async (target, fieldState, isWatched, isBlurEvent) => {
1132
- let error;
1238
+ const trigger = React.useCallback(async (name, options = {}) => {
1239
+ const fieldNames = convertToArrayPayload(name);
1133
1240
  let isValid;
1134
- let name = target.name;
1135
- const field = get(_fields, name);
1136
- if (formOptions.resolver) {
1137
- const { errors } = await executeResolver([name]);
1138
- error = get(errors, name);
1139
- if (isCheckBoxInput(target) && !error) {
1140
- const parentNodeName = getNodeParentName(name);
1141
- const valError = get(errors, parentNodeName, {});
1142
- valError.type && valError.message && (error = valError);
1143
- if (valError || get(_formState.errors, parentNodeName)) {
1144
- name = parentNodeName;
1145
- }
1146
- }
1147
- isValid = isEmptyObject(errors);
1241
+ subjectsRef.current.state.next({
1242
+ isValidating: true,
1243
+ });
1244
+ if (resolver) {
1245
+ const schemaResult = await executeResolverValidation(isUndefined(name) ? name : fieldNames);
1246
+ isValid = name
1247
+ ? fieldNames.every((name) => !get(schemaResult, name))
1248
+ : isEmptyObject(schemaResult);
1148
1249
  }
1149
1250
  else {
1150
- error = (await validateField(field, get(_formValues, name), isValidateAllFieldCriteria, formOptions.shouldUseNativeValidation))[name];
1151
- }
1152
- !isBlurEvent &&
1153
- _subjects.watch.next({
1154
- name,
1155
- type: target.type,
1156
- });
1157
- shouldRenderBaseOnError(false, name, error, fieldState, isValid, isWatched);
1158
- };
1159
- const handleChange = async ({ type, target, target: { value, name, type: inputType }, }) => {
1160
- const field = get(_fields, name);
1161
- if (field) {
1162
- let inputValue = inputType ? getFieldValue(field) : undefined;
1163
- inputValue = isUndefined(inputValue) ? value : inputValue;
1164
- const isBlurEvent = type === EVENTS.BLUR;
1165
- const { isOnBlur: isReValidateOnBlur, isOnChange: isReValidateOnChange } = getValidationModes(formOptions.reValidateMode);
1166
- const shouldSkipValidation = (!hasValidation(field._f, field._f.mount) &&
1167
- !formOptions.resolver &&
1168
- !get(_formState.errors, name)) ||
1169
- skipValidation(Object.assign({ isBlurEvent, isTouched: !!get(_formState.touchedFields, name), isSubmitted: _formState.isSubmitted, isReValidateOnBlur,
1170
- isReValidateOnChange }, validationMode));
1171
- const isWatched = !isBlurEvent && isFieldWatched(name);
1172
- if (!isUndefined(inputValue)) {
1173
- set(_formValues, name, inputValue);
1174
- }
1175
- const fieldState = updateTouchAndDirtyState(name, inputValue, isBlurEvent, false);
1176
- const shouldRender = !isEmptyObject(fieldState) || isWatched;
1177
- if (shouldSkipValidation) {
1178
- !isBlurEvent &&
1179
- _subjects.watch.next({
1180
- name,
1181
- type,
1182
- });
1183
- return (shouldRender &&
1184
- _subjects.state.next(isWatched ? { name } : Object.assign(Object.assign({}, fieldState), { name })));
1185
- }
1186
- _subjects.state.next({
1187
- isValidating: true,
1188
- });
1189
- if (get(_formState.errors, name) || !formOptions.delayError) {
1190
- handleValidate(target, fieldState, isWatched, isBlurEvent);
1251
+ if (name) {
1252
+ isValid = (await Promise.all(fieldNames
1253
+ .filter((fieldName) => get(fieldsRef.current, fieldName, {})._f)
1254
+ .map(async (fieldName) => await executeInlineValidation(fieldName, true)))).every(Boolean);
1191
1255
  }
1192
1256
  else {
1193
- _delayCallback =
1194
- _delayCallback || debounce(handleValidate, formOptions.delayError);
1195
- _delayCallback(target, fieldState, isWatched, isBlurEvent);
1196
- isWatched && _subjects.state.next({ name });
1257
+ await validateForm(fieldsRef.current);
1258
+ isValid = isEmptyObject(formStateRef.current.errors);
1197
1259
  }
1198
1260
  }
1199
- };
1200
- const _updateValidAndInputValue = (name, ref) => {
1201
- const field = get(_fields, name);
1261
+ subjectsRef.current.state.next(Object.assign(Object.assign({}, (isString(name) ? { name } : {})), { errors: formStateRef.current.errors, isValidating: false }));
1262
+ if (options.shouldFocus && !isValid) {
1263
+ focusFieldBy(fieldsRef.current, (key) => get(formStateRef.current.errors, key), name ? fieldNames : namesRef.current.mount);
1264
+ }
1265
+ readFormStateRef.current.isValid && updateIsValid();
1266
+ return isValid;
1267
+ }, [executeResolverValidation, executeInlineValidation]);
1268
+ const updateIsValidAndInputValue = (name, ref, shouldSkipValueAs) => {
1269
+ const field = get(fieldsRef.current, name);
1202
1270
  if (field) {
1203
- const fieldValue = get(_formValues, name);
1204
- const isValueUndefined = isUndefined(fieldValue);
1271
+ const isValueUndefined = isUndefined(field._f.value);
1205
1272
  const defaultValue = isValueUndefined
1206
- ? get(_defaultValues, name)
1207
- : fieldValue;
1208
- if (isUndefined(defaultValue) ||
1209
- (ref && ref.defaultChecked)) {
1210
- set(_formValues, name, getFieldValue(field));
1273
+ ? isUndefined(get(fieldArrayDefaultValuesRef.current, name))
1274
+ ? get(defaultValuesRef.current, name)
1275
+ : get(fieldArrayDefaultValuesRef.current, name)
1276
+ : field._f.value;
1277
+ if (!isUndefined(defaultValue)) {
1278
+ if (ref && ref.defaultChecked) {
1279
+ field._f.value = getFieldValue(field);
1280
+ }
1281
+ else if (shouldSkipValueAs) {
1282
+ field._f.value = defaultValue;
1283
+ }
1284
+ else {
1285
+ setFieldValue(name, defaultValue);
1286
+ }
1211
1287
  }
1212
- else {
1213
- setFieldValue(name, defaultValue);
1288
+ else if (isValueUndefined) {
1289
+ field._f.value = getFieldValue(field);
1214
1290
  }
1215
1291
  }
1216
- _isMounted && _proxyFormState.isValid && _updateValid();
1217
- };
1218
- const _getIsDirty = (name, data) => {
1219
- name && data && set(_formValues, name, data);
1220
- return !deepEqual(Object.assign({}, getValues()), _defaultValues);
1292
+ isMountedRef.current && readFormStateRef.current.isValid && updateIsValid();
1221
1293
  };
1222
- const _updateValid = async () => {
1223
- const isValid = formOptions.resolver
1224
- ? isEmptyObject((await executeResolver()).errors)
1225
- : await validateForm(_fields, true);
1226
- if (isValid !== _formState.isValid) {
1227
- _formState.isValid = isValid;
1228
- _subjects.state.next({
1294
+ const updateIsValid = React.useCallback(async (values = {}) => {
1295
+ const isValid = resolver
1296
+ ? isEmptyObject((await resolverRef.current(Object.assign(Object.assign({}, getFieldsValues(fieldsRef)), values), contextRef.current, getResolverOptions(namesRef.current.mount, fieldsRef.current, criteriaMode, shouldUseNativeValidation))).errors)
1297
+ : await validateForm(fieldsRef.current, true);
1298
+ if (isValid !== formStateRef.current.isValid) {
1299
+ formStateRef.current.isValid = isValid;
1300
+ subjectsRef.current.state.next({
1229
1301
  isValid,
1230
1302
  });
1231
1303
  }
1232
- };
1233
- const _setValues = (name, value, options) => Object.entries(value).forEach(([fieldKey, fieldValue]) => {
1304
+ }, [criteriaMode, shouldUseNativeValidation]);
1305
+ const setValues = React.useCallback((name, value, options) => Object.entries(value).forEach(([fieldKey, fieldValue]) => {
1234
1306
  const fieldName = `${name}.${fieldKey}`;
1235
- const field = get(_fields, fieldName);
1236
- const isFieldArray = _names.array.has(name);
1307
+ const field = get(fieldsRef.current, fieldName);
1308
+ const isFieldArray = namesRef.current.array.has(name);
1237
1309
  (isFieldArray || !isPrimitive(fieldValue) || (field && !field._f)) &&
1238
1310
  !isDateObject(fieldValue)
1239
- ? _setValues(fieldName, fieldValue, options)
1311
+ ? setValues(fieldName, fieldValue, options)
1240
1312
  : setFieldValue(fieldName, fieldValue, options, true, !field);
1241
- });
1242
- const _getWatch = (fieldNames, defaultValue, isGlobal) => {
1243
- const fieldValues = Object.assign({}, (_isMounted
1244
- ? Object.assign({}, Object.assign(Object.assign({}, _defaultValues), _formValues)) : isUndefined(defaultValue)
1245
- ? _defaultValues
1246
- : defaultValue));
1247
- if (!fieldNames) {
1248
- isGlobal && (_names.watchAll = true);
1249
- return fieldValues;
1250
- }
1251
- const result = [];
1252
- for (const fieldName of convertToArrayPayload(fieldNames)) {
1253
- isGlobal && _names.watch.add(fieldName);
1254
- result.push(get(fieldValues, fieldName));
1255
- }
1256
- return Array.isArray(fieldNames)
1257
- ? result
1258
- : isObject(result[0])
1259
- ? Object.assign({}, result[0]) : Array.isArray(result[0])
1260
- ? [...result[0]]
1261
- : result[0];
1262
- };
1263
- const _updateFormValues = (defaultValues, name = '') => {
1264
- for (const key in defaultValues) {
1265
- const value = defaultValues[key];
1266
- const fieldName = name + (name ? '.' : '') + key;
1267
- const field = get(_fields, fieldName);
1268
- if (!field || !field._f) {
1269
- if (isObject(value) || Array.isArray(value)) {
1270
- _updateFormValues(value, fieldName);
1271
- }
1272
- else if (!field) {
1273
- set(_formValues, fieldName, value);
1274
- }
1275
- }
1276
- }
1277
- };
1278
- const _bathFieldArrayUpdate = (keyName, name, method, args, updatedFieldArrayValues = [], shouldSet = true) => {
1279
- _isInAction = true;
1280
- if (get(_fields, name)) {
1281
- const output = method(get(_fields, name), args.argA, args.argB);
1282
- shouldSet && set(_fields, name, output);
1283
- }
1284
- set(_formValues, name, updatedFieldArrayValues);
1285
- if (Array.isArray(get(_formState.errors, name))) {
1286
- const output = method(get(_formState.errors, name), args.argA, args.argB);
1287
- shouldSet && set(_formState.errors, name, output);
1288
- unsetEmptyArray(_formState.errors, name);
1289
- }
1290
- if (_proxyFormState.touchedFields && get(_formState.touchedFields, name)) {
1291
- const output = method(get(_formState.touchedFields, name), args.argA, args.argB);
1292
- shouldSet && set(_formState.touchedFields, name, output);
1293
- unsetEmptyArray(_formState.touchedFields, name);
1294
- }
1295
- if (_proxyFormState.dirtyFields || _proxyFormState.isDirty) {
1296
- set(_formState.dirtyFields, name, setFieldArrayDirtyFields(omitKey(updatedFieldArrayValues, keyName), get(_defaultValues, name, []), get(_formState.dirtyFields, name, [])));
1297
- updatedFieldArrayValues &&
1298
- set(_formState.dirtyFields, name, setFieldArrayDirtyFields(omitKey(updatedFieldArrayValues, keyName), get(_defaultValues, name, []), get(_formState.dirtyFields, name, [])));
1299
- unsetEmptyArray(_formState.dirtyFields, name);
1300
- }
1301
- _subjects.state.next({
1302
- isDirty: _getIsDirty(name, omitKey(updatedFieldArrayValues, keyName)),
1303
- dirtyFields: _formState.dirtyFields,
1304
- errors: _formState.errors,
1305
- isValid: _formState.isValid,
1306
- });
1307
- };
1308
- const _getFieldArrayValue = (name) => get(_isMounted ? _formValues : _defaultValues, name, []);
1313
+ }), [trigger]);
1309
1314
  const setValue = (name, value, options = {}) => {
1310
- const field = get(_fields, name);
1311
- const isFieldArray = _names.array.has(name);
1315
+ const field = get(fieldsRef.current, name);
1316
+ const isFieldArray = namesRef.current.array.has(name);
1312
1317
  if (isFieldArray) {
1313
- _subjects.array.next({
1318
+ subjectsRef.current.array.next({
1314
1319
  values: value,
1315
1320
  name,
1316
1321
  isReset: true,
1317
1322
  });
1318
- if ((_proxyFormState.isDirty || _proxyFormState.dirtyFields) &&
1323
+ if ((readFormStateRef.current.isDirty ||
1324
+ readFormStateRef.current.dirtyFields) &&
1319
1325
  options.shouldDirty) {
1320
- set(_formState.dirtyFields, name, setFieldArrayDirtyFields(value, get(_defaultValues, name, []), get(_formState.dirtyFields, name, [])));
1321
- _subjects.state.next({
1326
+ set(formStateRef.current.dirtyFields, name, setFieldArrayDirtyFields(value, get(defaultValuesRef.current, name, []), get(formStateRef.current.dirtyFields, name, [])));
1327
+ subjectsRef.current.state.next({
1322
1328
  name,
1323
- dirtyFields: _formState.dirtyFields,
1324
- isDirty: _getIsDirty(name, value),
1329
+ dirtyFields: formStateRef.current.dirtyFields,
1330
+ isDirty: getIsDirty(name, value),
1325
1331
  });
1326
1332
  }
1327
- !value.length && set(_formValues, name, []);
1333
+ !value.length &&
1334
+ set(fieldsRef.current, name, []) &&
1335
+ set(fieldArrayDefaultValuesRef.current, name, []);
1328
1336
  }
1329
- set(_formValues, name, value);
1330
1337
  ((field && !field._f) || isFieldArray) && !isNullOrUndefined(value)
1331
- ? _setValues(name, value, isFieldArray ? {} : options)
1338
+ ? setValues(name, value, isFieldArray ? {} : options)
1332
1339
  : setFieldValue(name, value, options, true, !field);
1333
- isFieldWatched(name) && _subjects.state.next({});
1334
- _subjects.watch.next({
1335
- name,
1336
- });
1340
+ isFieldWatched(name) && subjectsRef.current.state.next({});
1341
+ subjectsRef.current.watch.next({ name, values: getValues() });
1337
1342
  };
1338
- const trigger = async (name, options = {}) => {
1339
- const fieldNames = convertToArrayPayload(name);
1343
+ const handleValidate = async (target, fieldState, isWatched, isBlurEvent) => {
1344
+ let error;
1340
1345
  let isValid;
1341
- _subjects.state.next({
1342
- isValidating: true,
1343
- });
1344
- if (formOptions.resolver) {
1345
- const schemaResult = await executeResolverValidation(isUndefined(name) ? name : fieldNames);
1346
- isValid = name
1347
- ? fieldNames.every((name) => !get(schemaResult, name))
1348
- : isEmptyObject(schemaResult);
1346
+ let name = target.name;
1347
+ const field = get(fieldsRef.current, name);
1348
+ if (resolver) {
1349
+ const { errors } = await resolverRef.current(getFieldsValues(fieldsRef), contextRef.current, getResolverOptions([name], fieldsRef.current, criteriaMode, shouldUseNativeValidation));
1350
+ error = get(errors, name);
1351
+ if (isCheckBoxInput(target) && !error) {
1352
+ const parentNodeName = getNodeParentName(name);
1353
+ const currentError = get(errors, parentNodeName, {});
1354
+ currentError.type && currentError.message && (error = currentError);
1355
+ if (currentError || get(formStateRef.current.errors, parentNodeName)) {
1356
+ name = parentNodeName;
1357
+ }
1358
+ }
1359
+ isValid = isEmptyObject(errors);
1349
1360
  }
1350
1361
  else {
1351
- if (name) {
1352
- isValid = (await Promise.all(fieldNames
1353
- .filter((fieldName) => get(_fields, fieldName, {})._f)
1354
- .map(async (fieldName) => await executeBuildinValidation(fieldName, true)))).every(Boolean);
1362
+ error = (await validateField(field, isValidateAllFieldCriteria, shouldUseNativeValidation))[name];
1363
+ }
1364
+ !isBlurEvent &&
1365
+ subjectsRef.current.watch.next({
1366
+ name,
1367
+ type: target.type,
1368
+ values: getValues(),
1369
+ });
1370
+ shouldRenderBaseOnError(false, name, error, fieldState, isValid, isWatched);
1371
+ };
1372
+ const handleChange = React.useCallback(async ({ type, target, target: { value, name, type: inputType } }) => {
1373
+ const field = get(fieldsRef.current, name);
1374
+ if (field) {
1375
+ let inputValue = inputType ? getFieldValue(field) : undefined;
1376
+ inputValue = isUndefined(inputValue) ? value : inputValue;
1377
+ const isBlurEvent = type === EVENTS.BLUR;
1378
+ const { isOnBlur: isReValidateOnBlur, isOnChange: isReValidateOnChange, } = getValidationModes(reValidateMode);
1379
+ const shouldSkipValidation = (!hasValidation(field._f, field._f.mount) &&
1380
+ !resolver &&
1381
+ !get(formStateRef.current.errors, name)) ||
1382
+ skipValidation(Object.assign({ isBlurEvent, isTouched: !!get(formStateRef.current.touchedFields, name), isSubmitted: formStateRef.current.isSubmitted, isReValidateOnBlur,
1383
+ isReValidateOnChange }, validationMode));
1384
+ const isWatched = !isBlurEvent && isFieldWatched(name);
1385
+ if (!isUndefined(inputValue)) {
1386
+ field._f.value = inputValue;
1355
1387
  }
1356
- else {
1357
- await validateForm(_fields);
1358
- isValid = isEmptyObject(_formState.errors);
1388
+ const fieldState = updateTouchAndDirtyState(name, field._f.value, isBlurEvent, false);
1389
+ const shouldRender = !isEmptyObject(fieldState) || isWatched;
1390
+ if (shouldSkipValidation) {
1391
+ !isBlurEvent &&
1392
+ subjectsRef.current.watch.next({
1393
+ name,
1394
+ type,
1395
+ values: getValues(),
1396
+ });
1397
+ return (shouldRender &&
1398
+ subjectsRef.current.state.next(isWatched ? { name } : Object.assign(Object.assign({}, fieldState), { name })));
1359
1399
  }
1400
+ subjectsRef.current.state.next({
1401
+ isValidating: true,
1402
+ });
1403
+ handleValidate(target, fieldState, isWatched, isBlurEvent);
1360
1404
  }
1361
- _subjects.state.next(Object.assign(Object.assign({}, (isString(name) ? { name } : {})), { errors: _formState.errors, isValidating: false }));
1362
- if (options.shouldFocus && !isValid) {
1363
- focusFieldBy(_fields, (key) => get(_formState.errors, key), name ? fieldNames : _names.mount);
1364
- }
1365
- _proxyFormState.isValid && _updateValid();
1366
- return isValid;
1367
- };
1405
+ }, []);
1368
1406
  const getValues = (fieldNames) => {
1369
- const values = Object.assign(Object.assign({}, _defaultValues), _formValues);
1407
+ const values = Object.assign(Object.assign({}, defaultValuesRef.current), getFieldsValues(fieldsRef));
1370
1408
  return isUndefined(fieldNames)
1371
1409
  ? values
1372
1410
  : isString(fieldNames)
@@ -1375,51 +1413,73 @@ function createFormControl(props = {}) {
1375
1413
  };
1376
1414
  const clearErrors = (name) => {
1377
1415
  name
1378
- ? convertToArrayPayload(name).forEach((inputName) => unset(_formState.errors, inputName))
1379
- : (_formState.errors = {});
1380
- _subjects.state.next({
1381
- errors: _formState.errors,
1416
+ ? convertToArrayPayload(name).forEach((inputName) => unset(formStateRef.current.errors, inputName))
1417
+ : (formStateRef.current.errors = {});
1418
+ subjectsRef.current.state.next({
1419
+ errors: formStateRef.current.errors,
1382
1420
  });
1383
1421
  };
1384
1422
  const setError = (name, error, options) => {
1385
- const ref = ((get(_fields, name) || { _f: {} })._f || {}).ref;
1386
- set(_formState.errors, name, Object.assign(Object.assign({}, error), { ref }));
1387
- _subjects.state.next({
1423
+ const ref = ((get(fieldsRef.current, name) || { _f: {} })._f || {}).ref;
1424
+ set(formStateRef.current.errors, name, Object.assign(Object.assign({}, error), { ref }));
1425
+ subjectsRef.current.state.next({
1388
1426
  name,
1389
- errors: _formState.errors,
1427
+ errors: formStateRef.current.errors,
1390
1428
  isValid: false,
1391
1429
  });
1392
1430
  options && options.shouldFocus && ref && ref.focus && ref.focus();
1393
1431
  };
1432
+ const watchInternal = React.useCallback((fieldNames, defaultValue, isGlobal, formValues) => {
1433
+ const isArrayNames = Array.isArray(fieldNames);
1434
+ const fieldValues = formValues || isMountedRef.current
1435
+ ? Object.assign(Object.assign({}, defaultValuesRef.current), (formValues || getFieldsValues(fieldsRef))) : isUndefined(defaultValue)
1436
+ ? defaultValuesRef.current
1437
+ : isArrayNames
1438
+ ? defaultValue
1439
+ : { [fieldNames]: defaultValue };
1440
+ if (isUndefined(fieldNames)) {
1441
+ isGlobal && (namesRef.current.watchAll = true);
1442
+ return fieldValues;
1443
+ }
1444
+ const result = [];
1445
+ for (const fieldName of convertToArrayPayload(fieldNames)) {
1446
+ isGlobal && namesRef.current.watch.add(fieldName);
1447
+ result.push(get(fieldValues, fieldName));
1448
+ }
1449
+ return isArrayNames ? result : result[0];
1450
+ }, []);
1394
1451
  const watch = (fieldName, defaultValue) => isFunction(fieldName)
1395
- ? _subjects.watch.subscribe({
1396
- next: (info) => fieldName(_getWatch(undefined, defaultValue), info),
1452
+ ? subjectsRef.current.watch.subscribe({
1453
+ next: (info) => fieldName(watchInternal(undefined, defaultValue), info),
1397
1454
  })
1398
- : _getWatch(fieldName, defaultValue, true);
1455
+ : watchInternal(fieldName, defaultValue, true);
1399
1456
  const unregister = (name, options = {}) => {
1400
- for (const inputName of name ? convertToArrayPayload(name) : _names.mount) {
1401
- _names.mount.delete(inputName);
1402
- _names.array.delete(inputName);
1403
- if (get(_fields, inputName)) {
1404
- if (!options.keepValue) {
1405
- unset(_fields, inputName);
1406
- unset(_formValues, inputName);
1407
- }
1408
- !options.keepError && unset(_formState.errors, inputName);
1409
- !options.keepDirty && unset(_formState.dirtyFields, inputName);
1410
- !options.keepTouched && unset(_formState.touchedFields, inputName);
1411
- !formOptions.shouldUnregister &&
1457
+ for (const inputName of name
1458
+ ? convertToArrayPayload(name)
1459
+ : namesRef.current.mount) {
1460
+ namesRef.current.mount.delete(inputName);
1461
+ namesRef.current.array.delete(inputName);
1462
+ if (get(fieldsRef.current, inputName)) {
1463
+ !options.keepError && unset(formStateRef.current.errors, inputName);
1464
+ !options.keepValue && unset(fieldsRef.current, inputName);
1465
+ !options.keepDirty &&
1466
+ unset(formStateRef.current.dirtyFields, inputName);
1467
+ !options.keepTouched &&
1468
+ unset(formStateRef.current.touchedFields, inputName);
1469
+ !shouldUnregister &&
1412
1470
  !options.keepDefaultValue &&
1413
- unset(_defaultValues, inputName);
1471
+ unset(defaultValuesRef.current, inputName);
1414
1472
  }
1415
1473
  }
1416
- _subjects.watch.next({});
1417
- _subjects.state.next(Object.assign(Object.assign({}, _formState), (!options.keepDirty ? {} : { isDirty: _getIsDirty() })));
1418
- !options.keepIsValid && _updateValid();
1474
+ subjectsRef.current.watch.next({
1475
+ values: getValues(),
1476
+ });
1477
+ subjectsRef.current.state.next(Object.assign(Object.assign({}, formStateRef.current), (!options.keepDirty ? {} : { isDirty: getIsDirty() })));
1478
+ !options.keepIsValid && updateIsValid();
1419
1479
  };
1420
1480
  const registerFieldRef = (name, ref, options) => {
1421
1481
  register(name, options);
1422
- let field = get(_fields, name);
1482
+ let field = get(fieldsRef.current, name);
1423
1483
  const isRadioOrCheckbox = isRadioOrCheckboxFunction(ref);
1424
1484
  if (ref === field._f.ref ||
1425
1485
  (isRadioOrCheckbox &&
@@ -1433,76 +1493,77 @@ function createFormControl(props = {}) {
1433
1493
  ref,
1434
1494
  ], ref: { type: ref.type, name } }) : Object.assign(Object.assign({}, field._f), { ref }),
1435
1495
  };
1436
- set(_fields, name, field);
1437
- _updateValidAndInputValue(name, ref);
1496
+ set(fieldsRef.current, name, field);
1497
+ updateIsValidAndInputValue(name, ref);
1438
1498
  };
1439
- const register = (name, options = {}) => {
1440
- const field = get(_fields, name);
1441
- set(_fields, name, {
1499
+ const register = React.useCallback((name, options = {}) => {
1500
+ const field = get(fieldsRef.current, name);
1501
+ set(fieldsRef.current, name, {
1442
1502
  _f: Object.assign(Object.assign(Object.assign({}, (field && field._f ? field._f : { ref: { name } })), { name, mount: true }), options),
1443
1503
  });
1444
- if (options.value) {
1445
- set(_formValues, name, options.value);
1446
- }
1447
- if (!isUndefined(options.disabled) &&
1448
- field &&
1449
- field._f &&
1450
- field._f.ref.disabled !== options.disabled) {
1451
- set(_formValues, name, options.disabled ? undefined : field._f.ref.value);
1452
- }
1453
- _names.mount.add(name);
1454
- !field && _updateValidAndInputValue(name);
1504
+ namesRef.current.mount.add(name);
1505
+ !field && updateIsValidAndInputValue(name, undefined, true);
1455
1506
  return isWindowUndefined
1456
1507
  ? { name: name }
1457
- : Object.assign(Object.assign({ name }, (isUndefined(options.disabled)
1458
- ? {}
1459
- : { disabled: options.disabled })), { onChange: handleChange, onBlur: handleChange, ref: (ref) => {
1508
+ : {
1509
+ name,
1510
+ onChange: handleChange,
1511
+ onBlur: handleChange,
1512
+ ref: (ref) => {
1460
1513
  if (ref) {
1461
1514
  registerFieldRef(name, ref, options);
1462
1515
  }
1463
1516
  else {
1464
- const field = get(_fields, name, {});
1465
- const _shouldUnregister = formOptions.shouldUnregister || options.shouldUnregister;
1517
+ const field = get(fieldsRef.current, name, {});
1518
+ const shouldUnmount = shouldUnregister || options.shouldUnregister;
1466
1519
  if (field._f) {
1467
1520
  field._f.mount = false;
1521
+ // If initial state of field element is disabled,
1522
+ // value is not set on first "register"
1523
+ // re-sync the value in when it switched to enabled
1524
+ if (isUndefined(field._f.value)) {
1525
+ field._f.value = field._f.ref.value;
1526
+ }
1468
1527
  }
1469
- _shouldUnregister &&
1470
- !(isNameInFieldArray(_names.array, name) && _isInAction) &&
1471
- _names.unMount.add(name);
1528
+ shouldUnmount &&
1529
+ !(isNameInFieldArray(namesRef.current.array, name) &&
1530
+ inFieldArrayActionRef.current) &&
1531
+ namesRef.current.unMount.add(name);
1472
1532
  }
1473
- } });
1474
- };
1475
- const handleSubmit = (onValid, onInvalid) => async (e) => {
1533
+ },
1534
+ };
1535
+ }, []);
1536
+ const handleSubmit = React.useCallback((onValid, onInvalid) => async (e) => {
1476
1537
  if (e) {
1477
1538
  e.preventDefault && e.preventDefault();
1478
1539
  e.persist && e.persist();
1479
1540
  }
1480
1541
  let hasNoPromiseError = true;
1481
- let fieldValues = Object.assign({}, _formValues);
1482
- _subjects.state.next({
1542
+ let fieldValues = getFieldsValues(fieldsRef);
1543
+ subjectsRef.current.state.next({
1483
1544
  isSubmitting: true,
1484
1545
  });
1485
1546
  try {
1486
- if (formOptions.resolver) {
1487
- const { errors, values } = await executeResolver();
1488
- _formState.errors = errors;
1547
+ if (resolver) {
1548
+ const { errors, values } = await resolverRef.current(fieldValues, contextRef.current, getResolverOptions(namesRef.current.mount, fieldsRef.current, criteriaMode, shouldUseNativeValidation));
1549
+ formStateRef.current.errors = errors;
1489
1550
  fieldValues = values;
1490
1551
  }
1491
1552
  else {
1492
- await validateForm(_fields);
1553
+ await validateForm(fieldsRef.current);
1493
1554
  }
1494
- if (isEmptyObject(_formState.errors) &&
1495
- Object.keys(_formState.errors).every((name) => get(fieldValues, name))) {
1496
- _subjects.state.next({
1555
+ if (isEmptyObject(formStateRef.current.errors) &&
1556
+ Object.keys(formStateRef.current.errors).every((name) => get(fieldValues, name))) {
1557
+ subjectsRef.current.state.next({
1497
1558
  errors: {},
1498
1559
  isSubmitting: true,
1499
1560
  });
1500
1561
  await onValid(fieldValues, e);
1501
1562
  }
1502
1563
  else {
1503
- onInvalid && (await onInvalid(_formState.errors, e));
1504
- formOptions.shouldFocusError &&
1505
- focusFieldBy(_fields, (key) => get(_formState.errors, key), _names.mount);
1564
+ onInvalid && (await onInvalid(formStateRef.current.errors, e));
1565
+ shouldFocusError &&
1566
+ focusFieldBy(fieldsRef.current, (key) => get(formStateRef.current.errors, key), namesRef.current.mount);
1506
1567
  }
1507
1568
  }
1508
1569
  catch (err) {
@@ -1510,21 +1571,41 @@ function createFormControl(props = {}) {
1510
1571
  throw err;
1511
1572
  }
1512
1573
  finally {
1513
- _formState.isSubmitted = true;
1514
- _subjects.state.next({
1574
+ formStateRef.current.isSubmitted = true;
1575
+ subjectsRef.current.state.next({
1515
1576
  isSubmitted: true,
1516
1577
  isSubmitting: false,
1517
- isSubmitSuccessful: isEmptyObject(_formState.errors) && hasNoPromiseError,
1518
- submitCount: _formState.submitCount + 1,
1519
- errors: _formState.errors,
1578
+ isSubmitSuccessful: isEmptyObject(formStateRef.current.errors) && hasNoPromiseError,
1579
+ submitCount: formStateRef.current.submitCount + 1,
1580
+ errors: formStateRef.current.errors,
1520
1581
  });
1521
1582
  }
1583
+ }, [
1584
+ shouldFocusError,
1585
+ isValidateAllFieldCriteria,
1586
+ criteriaMode,
1587
+ shouldUseNativeValidation,
1588
+ ]);
1589
+ const registerAbsentFields = (defaultValues, name = '') => {
1590
+ for (const key in defaultValues) {
1591
+ const value = defaultValues[key];
1592
+ const fieldName = name + (name ? '.' : '') + key;
1593
+ const field = get(fieldsRef.current, fieldName);
1594
+ if (!field || !field._f) {
1595
+ if (isObject(value) || Array.isArray(value)) {
1596
+ registerAbsentFields(value, fieldName);
1597
+ }
1598
+ else if (!field) {
1599
+ register(fieldName, { value });
1600
+ }
1601
+ }
1602
+ }
1522
1603
  };
1523
1604
  const reset = (values, keepStateOptions = {}) => {
1524
- const updatedValues = values || _defaultValues;
1605
+ const updatedValues = values || defaultValuesRef.current;
1525
1606
  if (isWeb && !keepStateOptions.keepValues) {
1526
- for (const name of _names.mount) {
1527
- const field = get(_fields, name);
1607
+ for (const name of namesRef.current.mount) {
1608
+ const field = get(fieldsRef.current, name);
1528
1609
  if (field && field._f) {
1529
1610
  const inputRef = Array.isArray(field._f.refs)
1530
1611
  ? field._f.refs[0]
@@ -1538,160 +1619,71 @@ function createFormControl(props = {}) {
1538
1619
  }
1539
1620
  }
1540
1621
  if (!keepStateOptions.keepDefaultValues) {
1541
- _defaultValues = Object.assign({}, updatedValues);
1542
- _formValues = Object.assign({}, updatedValues);
1622
+ defaultValuesRef.current = Object.assign({}, updatedValues);
1623
+ fieldArrayDefaultValuesRef.current = Object.assign({}, updatedValues);
1543
1624
  }
1544
1625
  if (!keepStateOptions.keepValues) {
1545
- _fields = {};
1546
- _formValues = {};
1547
- _subjects.control.next({
1626
+ fieldsRef.current = {};
1627
+ subjectsRef.current.control.next({
1548
1628
  values: keepStateOptions.keepDefaultValues
1549
- ? _defaultValues
1629
+ ? defaultValuesRef.current
1550
1630
  : Object.assign({}, updatedValues),
1551
1631
  });
1552
- _subjects.watch.next({});
1553
- _subjects.array.next({
1632
+ subjectsRef.current.watch.next({
1633
+ values: Object.assign({}, updatedValues),
1634
+ });
1635
+ subjectsRef.current.array.next({
1554
1636
  values: Object.assign({}, updatedValues),
1555
1637
  isReset: true,
1556
1638
  });
1557
1639
  }
1558
- _names = {
1640
+ namesRef.current = {
1559
1641
  mount: new Set(),
1560
1642
  unMount: new Set(),
1561
1643
  array: new Set(),
1562
1644
  watch: new Set(),
1563
1645
  watchAll: false,
1564
1646
  };
1565
- _subjects.state.next({
1647
+ subjectsRef.current.state.next({
1566
1648
  submitCount: keepStateOptions.keepSubmitCount
1567
- ? _formState.submitCount
1649
+ ? formStateRef.current.submitCount
1568
1650
  : 0,
1569
1651
  isDirty: keepStateOptions.keepDirty
1570
- ? _formState.isDirty
1652
+ ? formStateRef.current.isDirty
1571
1653
  : keepStateOptions.keepDefaultValues
1572
- ? deepEqual(values, _defaultValues)
1654
+ ? deepEqual(values, defaultValuesRef.current)
1573
1655
  : false,
1574
1656
  isSubmitted: keepStateOptions.keepIsSubmitted
1575
- ? _formState.isSubmitted
1657
+ ? formStateRef.current.isSubmitted
1576
1658
  : false,
1577
- dirtyFields: keepStateOptions.keepDirty ? _formState.dirtyFields : {},
1659
+ dirtyFields: keepStateOptions.keepDirty
1660
+ ? formStateRef.current.dirtyFields
1661
+ : {},
1578
1662
  touchedFields: keepStateOptions.keepTouched
1579
- ? _formState.touchedFields
1663
+ ? formStateRef.current.touchedFields
1580
1664
  : {},
1581
- errors: keepStateOptions.keepErrors ? _formState.errors : {},
1665
+ errors: keepStateOptions.keepErrors ? formStateRef.current.errors : {},
1582
1666
  isSubmitting: false,
1583
1667
  isSubmitSuccessful: false,
1584
1668
  });
1585
- _isMounted = !!keepStateOptions.keepIsValid;
1669
+ isMountedRef.current = !!keepStateOptions.keepIsValid;
1586
1670
  };
1587
- const setFocus = (name) => get(_fields, name)._f.ref.focus();
1588
- return {
1589
- control: {
1590
- register,
1591
- unregister,
1592
- _setValues,
1593
- _getIsDirty,
1594
- _getWatch,
1595
- _updateValid,
1596
- _updateFormValues,
1597
- _bathFieldArrayUpdate,
1598
- _getFieldArrayValue,
1599
- _subjects,
1600
- _shouldUnregister: formOptions.shouldUnregister,
1601
- _fields,
1602
- _proxyFormState,
1603
- get _formValues() {
1604
- return _formValues;
1605
- },
1606
- set _formValues(value) {
1607
- _formValues = value;
1608
- },
1609
- get _isMounted() {
1610
- return _isMounted;
1611
- },
1612
- set _isMounted(value) {
1613
- _isMounted = value;
1614
- },
1615
- get _defaultValues() {
1616
- return _defaultValues;
1617
- },
1618
- set _defaultValues(value) {
1619
- _defaultValues = value;
1620
- },
1621
- get _names() {
1622
- return _names;
1623
- },
1624
- set _names(value) {
1625
- _names = value;
1626
- },
1627
- _isInAction: {
1628
- get val() {
1629
- return _isInAction;
1630
- },
1631
- set val(value) {
1632
- _isInAction = value;
1633
- },
1634
- },
1635
- _formState: {
1636
- get val() {
1637
- return _formState;
1638
- },
1639
- set val(value) {
1640
- _formState = value;
1641
- },
1642
- },
1643
- _updateProps: (options) => {
1644
- formOptions = Object.assign(Object.assign({}, defaultOptions), options);
1645
- },
1646
- },
1647
- trigger,
1648
- register,
1649
- handleSubmit,
1650
- watch,
1651
- setValue,
1652
- getValues,
1653
- reset,
1654
- clearErrors,
1655
- unregister,
1656
- setError,
1657
- setFocus,
1658
- };
1659
- }
1660
-
1661
- var live = (ref) => !isHTMLElement(ref) || !document.contains(ref);
1662
-
1663
- function useForm(props = {}) {
1664
- const _formControl = React.useRef();
1665
- const [formState, updateFormState] = React.useState({
1666
- isDirty: false,
1667
- isValidating: false,
1668
- dirtyFields: {},
1669
- isSubmitted: false,
1670
- submitCount: 0,
1671
- touchedFields: {},
1672
- isSubmitting: false,
1673
- isSubmitSuccessful: false,
1674
- isValid: false,
1675
- errors: {},
1676
- });
1677
- _formControl.current
1678
- ? _formControl.current.control._updateProps(props)
1679
- : (_formControl.current = createFormControl(props));
1680
- const control = _formControl.current.control;
1671
+ const setFocus = (name) => get(fieldsRef.current, name)._f.ref.focus();
1681
1672
  React.useEffect(() => {
1682
- const formStateSubscription = control._subjects.state.subscribe({
1673
+ const formStateSubscription = subjectsRef.current.state.subscribe({
1683
1674
  next(formState) {
1684
- if (shouldRenderFormState(formState, control._proxyFormState, true)) {
1685
- control._formState.val = Object.assign(Object.assign({}, control._formState.val), formState);
1686
- updateFormState(Object.assign({}, control._formState.val));
1675
+ if (shouldRenderFormState(formState, readFormStateRef.current, true)) {
1676
+ formStateRef.current = Object.assign(Object.assign({}, formStateRef.current), formState);
1677
+ updateFormState(formStateRef.current);
1687
1678
  }
1688
1679
  },
1689
1680
  });
1690
- const useFieldArraySubscription = control._subjects.array.subscribe({
1681
+ const useFieldArraySubscription = subjectsRef.current.array.subscribe({
1691
1682
  next(state) {
1692
- if (state.values && state.name && control._proxyFormState.isValid) {
1693
- set(control._formValues, state.name, state.values);
1694
- control._updateValid();
1683
+ if (state.values && state.name && readFormStateRef.current.isValid) {
1684
+ const values = getFieldsValues(fieldsRef);
1685
+ set(values, state.name, state.values);
1686
+ updateIsValid(values);
1695
1687
  }
1696
1688
  },
1697
1689
  });
@@ -1699,49 +1691,82 @@ function useForm(props = {}) {
1699
1691
  formStateSubscription.unsubscribe();
1700
1692
  useFieldArraySubscription.unsubscribe();
1701
1693
  };
1702
- }, [control]);
1694
+ }, []);
1703
1695
  React.useEffect(() => {
1704
1696
  const unregisterFieldNames = [];
1705
- if (!control._isMounted) {
1706
- control._isMounted = true;
1707
- control._proxyFormState.isValid && control._updateValid();
1708
- !props.shouldUnregister &&
1709
- control._updateFormValues(control._defaultValues);
1710
- }
1711
- for (const name of control._names.unMount) {
1712
- const field = get(control._fields, name);
1697
+ const isLiveInDom = (ref) => !isHTMLElement(ref) || !document.contains(ref);
1698
+ if (!isMountedRef.current) {
1699
+ isMountedRef.current = true;
1700
+ readFormStateRef.current.isValid && updateIsValid();
1701
+ !shouldUnregister && registerAbsentFields(defaultValuesRef.current);
1702
+ }
1703
+ for (const name of namesRef.current.unMount) {
1704
+ const field = get(fieldsRef.current, name);
1713
1705
  field &&
1714
- (field._f.refs ? field._f.refs.every(live) : live(field._f.ref)) &&
1706
+ (field._f.refs
1707
+ ? field._f.refs.every(isLiveInDom)
1708
+ : isLiveInDom(field._f.ref)) &&
1715
1709
  unregisterFieldNames.push(name);
1716
1710
  }
1717
1711
  unregisterFieldNames.length &&
1718
- _formControl.current.unregister(unregisterFieldNames);
1719
- control._names.unMount = new Set();
1712
+ unregister(unregisterFieldNames);
1713
+ namesRef.current.unMount = new Set();
1720
1714
  });
1721
- return Object.assign(Object.assign({}, _formControl.current), { formState: getProxyFormState(formState, control._proxyFormState) });
1715
+ return {
1716
+ control: React.useMemo(() => ({
1717
+ register,
1718
+ inFieldArrayActionRef,
1719
+ getIsDirty,
1720
+ subjectsRef,
1721
+ watchInternal,
1722
+ fieldsRef,
1723
+ updateIsValid,
1724
+ namesRef,
1725
+ readFormStateRef,
1726
+ formStateRef,
1727
+ defaultValuesRef,
1728
+ fieldArrayDefaultValuesRef,
1729
+ setValues,
1730
+ unregister,
1731
+ shouldUnmount: shouldUnregister,
1732
+ }), []),
1733
+ formState: getProxyFormState(isProxyEnabled, formState, readFormStateRef),
1734
+ trigger,
1735
+ register,
1736
+ handleSubmit,
1737
+ watch: React.useCallback(watch, []),
1738
+ setValue: React.useCallback(setValue, [setValues]),
1739
+ getValues: React.useCallback(getValues, []),
1740
+ reset: React.useCallback(reset, []),
1741
+ clearErrors: React.useCallback(clearErrors, []),
1742
+ unregister: React.useCallback(unregister, []),
1743
+ setError: React.useCallback(setError, []),
1744
+ setFocus: React.useCallback(setFocus, []),
1745
+ };
1722
1746
  }
1723
1747
 
1724
1748
  function useWatch(props) {
1749
+ const { control, name, defaultValue } = props || {};
1725
1750
  const methods = useFormContext();
1726
- const { control = methods.control, name, defaultValue, disabled, } = props || {};
1727
- const _name = React.useRef(name);
1728
- _name.current = name;
1751
+ const nameRef = React.useRef(name);
1752
+ nameRef.current = name;
1753
+ const { watchInternal, subjectsRef } = control || methods.control;
1729
1754
  const [value, updateValue] = React.useState(isUndefined(defaultValue)
1730
- ? control._getWatch(name)
1755
+ ? watchInternal(name)
1731
1756
  : defaultValue);
1732
1757
  React.useEffect(() => {
1733
- const watchSubscription = control._subjects.watch.subscribe({
1734
- next: ({ name }) => (!_name.current ||
1735
- !name ||
1736
- convertToArrayPayload(_name.current).some((fieldName) => name &&
1758
+ watchInternal(name);
1759
+ const watchSubscription = subjectsRef.current.watch.subscribe({
1760
+ next: ({ name: inputName, values }) => (!nameRef.current ||
1761
+ !inputName ||
1762
+ convertToArrayPayload(nameRef.current).some((fieldName) => inputName &&
1737
1763
  fieldName &&
1738
- (fieldName.startsWith(name) ||
1739
- name.startsWith(fieldName)))) &&
1740
- updateValue(control._getWatch(_name.current, defaultValue)),
1764
+ (fieldName.startsWith(inputName) ||
1765
+ inputName.startsWith(fieldName)))) &&
1766
+ updateValue(watchInternal(nameRef.current, defaultValue, false, values)),
1741
1767
  });
1742
- disabled && watchSubscription.unsubscribe();
1743
1768
  return () => watchSubscription.unsubscribe();
1744
- }, [disabled, control, defaultValue]);
1769
+ }, []);
1745
1770
  return value;
1746
1771
  }
1747
1772