react-hook-form 7.23.0-next.0 → 7.24.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.
@@ -2,7 +2,7 @@ import React from 'react';
2
2
 
3
3
  var isCheckBoxInput = (element) => element.type === 'checkbox';
4
4
 
5
- var isDateObject = (data) => data instanceof Date;
5
+ var isDateObject = (value) => value instanceof Date;
6
6
 
7
7
  var isNullOrUndefined = (value) => value == null;
8
8
 
@@ -22,20 +22,20 @@ var getNodeParentName = (name) => name.substring(0, name.search(/.\d/)) || name;
22
22
 
23
23
  var isNameInFieldArray = (names, name) => [...names].some((current) => getNodeParentName(name) === current);
24
24
 
25
- var compact = (value) => (value || []).filter(Boolean);
25
+ var compact = (value) => value.filter(Boolean);
26
26
 
27
27
  var isUndefined = (val) => val === undefined;
28
28
 
29
29
  var get = (obj, path, defaultValue) => {
30
- if (isObject(obj) && path) {
31
- const result = compact(path.split(/[,[\].]+?/)).reduce((result, key) => (isNullOrUndefined(result) ? result : result[key]), obj);
32
- return isUndefined(result) || result === obj
33
- ? isUndefined(obj[path])
34
- ? defaultValue
35
- : obj[path]
36
- : result;
30
+ if (!path || !isObject(obj)) {
31
+ return defaultValue;
37
32
  }
38
- return undefined;
33
+ const result = compact(path.split(/[,[\].]+?/)).reduce((result, key) => isNullOrUndefined(result) ? result : result[key], obj);
34
+ return isUndefined(result) || result === obj
35
+ ? isUndefined(obj[path])
36
+ ? defaultValue
37
+ : obj[path]
38
+ : result;
39
39
  };
40
40
 
41
41
  const EVENTS = {
@@ -142,8 +142,10 @@ function useFormState(props) {
142
142
  errors: false,
143
143
  });
144
144
  const _name = React.useRef(name);
145
+ const _mounted = React.useRef(true);
145
146
  _name.current = name;
146
- const callback = React.useCallback((value) => shouldSubscribeByName(_name.current, value.name, exact) &&
147
+ const callback = React.useCallback((value) => _mounted.current &&
148
+ shouldSubscribeByName(_name.current, value.name, exact) &&
147
149
  shouldRenderFormState(value, _localProxyFormState.current) &&
148
150
  updateFormState(Object.assign(Object.assign({}, control._formState), value)), [control, exact]);
149
151
  useSubscribe({
@@ -151,6 +153,9 @@ function useFormState(props) {
151
153
  callback,
152
154
  subject: control._subjects.state,
153
155
  });
156
+ React.useEffect(() => () => {
157
+ _mounted.current = false;
158
+ }, []);
154
159
  return getProxyFormState(formState, control._proxyFormState, _localProxyFormState.current, false);
155
160
  }
156
161
 
@@ -226,9 +231,7 @@ function useController(props) {
226
231
  control,
227
232
  name,
228
233
  });
229
- const _name = React.useRef(name);
230
- _name.current = name;
231
- const registerProps = control.register(name, Object.assign(Object.assign({}, props.rules), { value }));
234
+ const _registerProps = React.useRef(control.register(name, Object.assign(Object.assign({}, props.rules), { value })));
232
235
  React.useEffect(() => {
233
236
  const updateMounted = (name, value) => {
234
237
  const field = get(control._fields, name);
@@ -248,27 +251,27 @@ function useController(props) {
248
251
  }, [name, control, isArrayField, shouldUnregister]);
249
252
  return {
250
253
  field: {
251
- onChange: (event) => {
252
- registerProps.onChange({
254
+ name,
255
+ value,
256
+ onChange: React.useCallback((event) => {
257
+ _registerProps.current.onChange({
253
258
  target: {
254
259
  value: getEventValue(event),
255
260
  name: name,
256
261
  },
257
262
  type: EVENTS.CHANGE,
258
263
  });
259
- },
260
- onBlur: () => {
261
- registerProps.onBlur({
264
+ }, [name]),
265
+ onBlur: React.useCallback(() => {
266
+ _registerProps.current.onBlur({
262
267
  target: {
263
268
  value: get(control._formValues, name),
264
269
  name: name,
265
270
  },
266
271
  type: EVENTS.BLUR,
267
272
  });
268
- },
269
- name,
270
- value,
271
- ref: (elm) => {
273
+ }, [name, control]),
274
+ ref: React.useCallback((elm) => {
272
275
  const field = get(control._fields, name);
273
276
  if (elm && field && elm.focus) {
274
277
  field._f.ref = {
@@ -277,13 +280,13 @@ function useController(props) {
277
280
  reportValidity: () => elm.reportValidity(),
278
281
  };
279
282
  }
280
- },
283
+ }, [name, control]),
281
284
  },
282
285
  formState,
283
286
  fieldState: {
284
287
  invalid: !!get(formState.errors, name),
285
- isDirty: !!get(formState.dirtyFields, name),
286
- isTouched: !!get(formState.touchedFields, name),
288
+ isDirty: get(formState.dirtyFields, name),
289
+ isTouched: get(formState.touchedFields, name),
287
290
  error: get(formState.errors, name),
288
291
  },
289
292
  };
@@ -343,6 +346,14 @@ const focusFieldBy = (fields, callback, fieldsNames) => {
343
346
  }
344
347
  };
345
348
 
349
+ var generateId = () => {
350
+ const d = typeof performance === 'undefined' ? Date.now() : performance.now() * 1000;
351
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
352
+ const r = (Math.random() * 16 + d) % 16 | 0;
353
+ return (c == 'x' ? r : (r & 0x3) | 0x8).toString(16);
354
+ });
355
+ };
356
+
346
357
  var getFocusFieldName = (name, index, options = {}) => options.shouldFocus || isUndefined(options.shouldFocus)
347
358
  ? options.focusName ||
348
359
  `${name}.${isUndefined(options.focusIndex) ? index : options.focusIndex}.`
@@ -354,20 +365,8 @@ var isWatched = (name, _names, isBlurEvent) => !isBlurEvent &&
354
365
  [..._names.watch].some((watchName) => name.startsWith(watchName) &&
355
366
  /^\.\w+/.test(name.slice(watchName.length))));
356
367
 
357
- var generateId = () => {
358
- const d = typeof performance === 'undefined' ? Date.now() : performance.now() * 1000;
359
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
360
- const r = (Math.random() * 16 + d) % 16 | 0;
361
- return (c == 'x' ? r : (r & 0x3) | 0x8).toString(16);
362
- });
363
- };
364
-
365
- var mapCurrentIds = (values, keyName, _fieldIds) => values.map((value, index) => (Object.assign(Object.assign({}, value), { [keyName]: _fieldIds && _fieldIds.current[index]
366
- ? _fieldIds.current[index][keyName]
367
- : value[keyName] || generateId() })));
368
-
369
368
  function append(data, value) {
370
- return [...convertToArrayPayload(data), ...convertToArrayPayload(value)];
369
+ return [...data, ...convertToArrayPayload(value)];
371
370
  }
372
371
 
373
372
  function cloneObject(data) {
@@ -406,18 +405,16 @@ function insert(data, index, value) {
406
405
  }
407
406
 
408
407
  var moveArrayAt = (data, from, to) => {
409
- if (Array.isArray(data)) {
410
- if (isUndefined(data[to])) {
411
- data[to] = undefined;
412
- }
413
- data.splice(to, 0, data.splice(from, 1)[0]);
414
- return data;
408
+ if (!Array.isArray(data)) {
409
+ return [];
410
+ }
411
+ if (isUndefined(data[to])) {
412
+ data[to] = undefined;
415
413
  }
416
- return [];
414
+ data.splice(to, 0, data.splice(from, 1)[0]);
415
+ return data;
417
416
  };
418
417
 
419
- var omitKeys = (fields, keyName) => fields.map((field = {}) => omit(field, keyName));
420
-
421
418
  function prepend(data, value) {
422
419
  return [...convertToArrayPayload(value), ...convertToArrayPayload(data)];
423
420
  }
@@ -447,8 +444,8 @@ var updateAt = (fieldValues, index, value) => {
447
444
  const useFieldArray = (props) => {
448
445
  const methods = useFormContext();
449
446
  const { control = methods.control, name, keyName = 'id', shouldUnregister, } = props;
450
- const _shouldKeepKeyName = React.useRef(get(control._getFieldArray(name)[0], keyName));
451
- const [fields, setFields] = React.useState(mapCurrentIds(control._getFieldArray(name), keyName));
447
+ const [fields, setFields] = React.useState(control._getFieldArray(name));
448
+ const ids = React.useRef(control._getFieldArray(name).map(generateId));
452
449
  const _fieldIds = React.useRef(fields);
453
450
  const _name = React.useRef(name);
454
451
  const _actioned = React.useRef(false);
@@ -457,98 +454,100 @@ const useFieldArray = (props) => {
457
454
  control._names.array.add(name);
458
455
  const callback = React.useCallback(({ values, name: fieldArrayName }) => {
459
456
  if (fieldArrayName === _name.current || !fieldArrayName) {
460
- setFields(mapCurrentIds(get(values, _name.current, []), keyName));
457
+ const fieldValues = get(values, _name.current, []);
458
+ setFields(fieldValues);
459
+ ids.current = fieldValues.map(generateId);
461
460
  }
462
- }, [keyName]);
461
+ }, []);
463
462
  useSubscribe({
464
463
  callback,
465
464
  subject: control._subjects.array,
466
465
  });
467
- const updateValues = React.useCallback((updatedFieldArrayValuesWithKey, hasKey = _shouldKeepKeyName.current) => {
468
- const updatedFieldArrayValues = hasKey
469
- ? updatedFieldArrayValuesWithKey
470
- : omitKeys(updatedFieldArrayValuesWithKey, keyName);
471
- hasKey && (_shouldKeepKeyName.current = true);
466
+ const updateValues = React.useCallback((updatedFieldArrayValues) => {
472
467
  _actioned.current = true;
473
468
  set(control._formValues, name, updatedFieldArrayValues);
474
- return updatedFieldArrayValues;
475
- }, [control, name, keyName]);
469
+ }, [control, name]);
476
470
  const append$1 = (value, options) => {
477
471
  const appendValue = convertToArrayPayload(cloneObject(value));
478
- const updatedFieldArrayValuesWithKey = append(mapCurrentIds(control._getFieldArray(name), keyName, _fieldIds), mapCurrentIds(appendValue, keyName));
479
- const fieldArrayValues = updateValues(updatedFieldArrayValuesWithKey, appendValue[0][keyName]);
480
- control._names.focus = getFocusFieldName(name, fieldArrayValues.length - 1, options);
481
- setFields(updatedFieldArrayValuesWithKey);
472
+ const updatedFieldArrayValues = append(control._getFieldArray(name), appendValue);
473
+ control._names.focus = getFocusFieldName(name, updatedFieldArrayValues.length - 1, options);
474
+ ids.current = append(ids.current, appendValue.map(generateId));
475
+ setFields(updatedFieldArrayValues);
476
+ updateValues(updatedFieldArrayValues);
482
477
  control._updateFieldArray(name, append, {
483
478
  argA: fillEmptyArray(value),
484
- }, fieldArrayValues);
479
+ }, updatedFieldArrayValues);
485
480
  };
486
481
  const prepend$1 = (value, options) => {
487
482
  const prependValue = convertToArrayPayload(cloneObject(value));
488
- const updatedFieldArrayValuesWithKey = prepend(mapCurrentIds(control._getFieldArray(name), keyName, _fieldIds), mapCurrentIds(prependValue, keyName));
489
- const fieldArrayValues = updateValues(updatedFieldArrayValuesWithKey, prependValue[0][keyName]);
483
+ const updatedFieldArrayValues = prepend(control._getFieldArray(name), prependValue);
490
484
  control._names.focus = getFocusFieldName(name, 0, options);
491
- setFields(updatedFieldArrayValuesWithKey);
485
+ ids.current = prepend(ids.current, prependValue.map(generateId));
486
+ setFields(updatedFieldArrayValues);
487
+ updateValues(updatedFieldArrayValues);
492
488
  control._updateFieldArray(name, prepend, {
493
489
  argA: fillEmptyArray(value),
494
- }, fieldArrayValues);
490
+ }, updatedFieldArrayValues);
495
491
  };
496
492
  const remove = (index) => {
497
- const updatedFieldArrayValuesWithKey = removeArrayAt(mapCurrentIds(control._getFieldArray(name), keyName, _fieldIds), index);
498
- const fieldArrayValues = updateValues(updatedFieldArrayValuesWithKey);
499
- setFields(updatedFieldArrayValuesWithKey);
493
+ const updatedFieldArrayValues = removeArrayAt(control._getFieldArray(name), index);
494
+ ids.current = removeArrayAt(ids.current, index);
495
+ setFields(updatedFieldArrayValues);
496
+ updateValues(updatedFieldArrayValues);
500
497
  control._updateFieldArray(name, removeArrayAt, {
501
498
  argA: index,
502
- }, fieldArrayValues);
499
+ }, updatedFieldArrayValues);
503
500
  };
504
501
  const insert$1 = (index, value, options) => {
505
502
  const insertValue = convertToArrayPayload(cloneObject(value));
506
- const updatedFieldArrayValuesWithKey = insert(mapCurrentIds(control._getFieldArray(name), keyName, _fieldIds), index, mapCurrentIds(insertValue, keyName));
507
- const fieldArrayValues = updateValues(updatedFieldArrayValuesWithKey, insertValue[0][keyName]);
503
+ const updatedFieldArrayValues = insert(control._getFieldArray(name), index, insertValue);
504
+ updateValues(updatedFieldArrayValues);
508
505
  control._names.focus = getFocusFieldName(name, index, options);
509
- setFields(updatedFieldArrayValuesWithKey);
506
+ ids.current = insert(ids.current, index, insertValue.map(generateId));
507
+ setFields(updatedFieldArrayValues);
510
508
  control._updateFieldArray(name, insert, {
511
509
  argA: index,
512
510
  argB: fillEmptyArray(value),
513
- }, fieldArrayValues);
511
+ }, updatedFieldArrayValues);
514
512
  };
515
513
  const swap = (indexA, indexB) => {
516
- const updatedFieldArrayValuesWithKey = mapCurrentIds(control._getFieldArray(name), keyName, _fieldIds);
517
- swapArrayAt(updatedFieldArrayValuesWithKey, indexA, indexB);
518
- const fieldArrayValues = updateValues(updatedFieldArrayValuesWithKey);
519
- setFields(updatedFieldArrayValuesWithKey);
514
+ const updatedFieldArrayValues = control._getFieldArray(name);
515
+ swapArrayAt(updatedFieldArrayValues, indexA, indexB);
516
+ swapArrayAt(ids.current, indexA, indexB);
517
+ setFields(updatedFieldArrayValues);
518
+ updateValues(updatedFieldArrayValues);
520
519
  control._updateFieldArray(name, swapArrayAt, {
521
520
  argA: indexA,
522
521
  argB: indexB,
523
- }, fieldArrayValues, false);
522
+ }, updatedFieldArrayValues, false);
524
523
  };
525
524
  const move = (from, to) => {
526
- const updatedFieldArrayValuesWithKey = mapCurrentIds(control._getFieldArray(name), keyName, _fieldIds);
527
- moveArrayAt(updatedFieldArrayValuesWithKey, from, to);
528
- const fieldArrayValues = updateValues(updatedFieldArrayValuesWithKey);
529
- setFields(updatedFieldArrayValuesWithKey);
525
+ const updatedFieldArrayValues = control._getFieldArray(name);
526
+ moveArrayAt(updatedFieldArrayValues, from, to);
527
+ moveArrayAt(ids.current, from, to);
528
+ setFields(updatedFieldArrayValues);
529
+ updateValues(updatedFieldArrayValues);
530
530
  control._updateFieldArray(name, moveArrayAt, {
531
531
  argA: from,
532
532
  argB: to,
533
- }, fieldArrayValues, false);
533
+ }, updatedFieldArrayValues, false);
534
534
  };
535
535
  const update = (index, value) => {
536
- const updatedFieldArrayValuesWithKey = mapCurrentIds(control._getFieldArray(name), keyName, _fieldIds);
537
- const updatedFieldArrayValues = updateAt(updatedFieldArrayValuesWithKey, index, value);
538
- _fieldIds.current = mapCurrentIds(updatedFieldArrayValues, keyName);
539
- const fieldArrayValues = updateValues(_fieldIds.current, get(value, keyName));
540
- setFields(_fieldIds.current);
536
+ const updatedFieldArrayValues = updateAt(control._getFieldArray(name), index, value);
537
+ ids.current = [...updatedFieldArrayValues].map((item, i) => !item || i === index ? generateId() : ids.current[i]);
538
+ setFields([...updatedFieldArrayValues]);
539
+ updateValues(updatedFieldArrayValues);
541
540
  control._updateFieldArray(name, updateAt, {
542
541
  argA: index,
543
542
  argB: value,
544
- }, fieldArrayValues, true, false, false);
543
+ }, updatedFieldArrayValues, true, false);
545
544
  };
546
545
  const replace = (value) => {
547
- const updateValue = convertToArrayPayload(value);
548
- const updatedFieldArrayValuesWithKey = mapCurrentIds(updateValue, keyName);
549
- const fieldArrayValues = updateValues(updatedFieldArrayValuesWithKey, updateValue[0][keyName]);
550
- setFields(updatedFieldArrayValuesWithKey);
551
- control._updateFieldArray(name, () => updatedFieldArrayValuesWithKey, {}, fieldArrayValues, true, false, false);
546
+ const updatedFieldArrayValues = convertToArrayPayload(value);
547
+ ids.current = updatedFieldArrayValues.map(generateId);
548
+ updateValues([...updatedFieldArrayValues]);
549
+ setFields([...updatedFieldArrayValues]);
550
+ control._updateFieldArray(name, () => updatedFieldArrayValues, {}, [...updatedFieldArrayValues], true, false);
552
551
  };
553
552
  React.useEffect(() => {
554
553
  control._stateFlags.action = false;
@@ -572,25 +571,24 @@ const useFieldArray = (props) => {
572
571
  focusFieldBy(control._fields, (key) => key.startsWith(control._names.focus));
573
572
  control._names.focus = '';
574
573
  control._proxyFormState.isValid && control._updateValid();
575
- }, [fields, name, control, keyName]);
574
+ }, [fields, name, control]);
576
575
  React.useEffect(() => {
577
576
  !get(control._formValues, name) && set(control._formValues, name, []);
578
577
  return () => {
579
- if (control._options.shouldUnregister || shouldUnregister) {
578
+ (control._options.shouldUnregister || shouldUnregister) &&
580
579
  control.unregister(name);
581
- }
582
580
  };
583
581
  }, [name, control, keyName, shouldUnregister]);
584
582
  return {
585
- swap: React.useCallback(swap, [updateValues, name, control, keyName]),
586
- move: React.useCallback(move, [updateValues, name, control, keyName]),
587
- prepend: React.useCallback(prepend$1, [updateValues, name, control, keyName]),
588
- append: React.useCallback(append$1, [updateValues, name, control, keyName]),
589
- remove: React.useCallback(remove, [updateValues, name, control, keyName]),
590
- insert: React.useCallback(insert$1, [updateValues, name, control, keyName]),
591
- update: React.useCallback(update, [updateValues, name, control, keyName]),
592
- replace: React.useCallback(replace, [updateValues, name, control, keyName]),
593
- fields: fields,
583
+ swap: React.useCallback(swap, [updateValues, name, control]),
584
+ move: React.useCallback(move, [updateValues, name, control]),
585
+ prepend: React.useCallback(prepend$1, [updateValues, name, control]),
586
+ append: React.useCallback(append$1, [updateValues, name, control]),
587
+ remove: React.useCallback(remove, [updateValues, name, control]),
588
+ insert: React.useCallback(insert$1, [updateValues, name, control]),
589
+ update: React.useCallback(update, [updateValues, name, control]),
590
+ replace: React.useCallback(replace, [updateValues, name, control]),
591
+ fields: React.useMemo(() => fields.map((field, index) => (Object.assign(Object.assign({}, field), { [keyName]: ids.current[index] || generateId() }))), [fields, keyName]),
594
592
  };
595
593
  };
596
594
 
@@ -679,7 +677,7 @@ var isWeb = typeof window !== 'undefined' &&
679
677
  typeof window.HTMLElement !== 'undefined' &&
680
678
  typeof document !== 'undefined';
681
679
 
682
- var live = (ref) => isHTMLElement(ref) && document.contains(ref);
680
+ var live = (ref) => isHTMLElement(ref) && ref.isConnected;
683
681
 
684
682
  function baseGet(object, updatePath) {
685
683
  const length = updatePath.slice(0, -1).length;
@@ -1145,24 +1143,25 @@ function createFormControl(props = {}) {
1145
1143
  }
1146
1144
  return isValid;
1147
1145
  };
1148
- const _updateFieldArray = (name, method, args, values = [], shouldSetValues = true, shouldSetFields = true, shouldSetError = true) => {
1146
+ const _updateFieldArray = (name, method, args, values = [], shouldSetValues = true, shouldSetFields = true) => {
1149
1147
  _stateFlags.action = true;
1150
- if (shouldSetFields && get(_fields, name)) {
1148
+ if (shouldSetFields && Array.isArray(get(_fields, name))) {
1151
1149
  const fieldValues = method(get(_fields, name), args.argA, args.argB);
1152
1150
  shouldSetValues && set(_fields, name, fieldValues);
1153
1151
  }
1154
- if (shouldSetError && Array.isArray(get(_formState.errors, name))) {
1152
+ if (_proxyFormState.errors &&
1153
+ shouldSetFields &&
1154
+ Array.isArray(get(_formState.errors, name))) {
1155
1155
  const errors = method(get(_formState.errors, name), args.argA, args.argB);
1156
1156
  shouldSetValues && set(_formState.errors, name, errors);
1157
1157
  unsetEmptyArray(_formState.errors, name);
1158
1158
  }
1159
- if (_proxyFormState.touchedFields && get(_formState.touchedFields, name)) {
1159
+ if (_proxyFormState.touchedFields &&
1160
+ Array.isArray(get(_formState.touchedFields, name))) {
1160
1161
  const touchedFields = method(get(_formState.touchedFields, name), args.argA, args.argB);
1161
- shouldSetValues &&
1162
- set(_formState.touchedFields, name, touchedFields);
1163
- unsetEmptyArray(_formState.touchedFields, name);
1162
+ shouldSetValues && set(_formState.touchedFields, name, touchedFields);
1164
1163
  }
1165
- if (_proxyFormState.dirtyFields || _proxyFormState.isDirty) {
1164
+ if (_proxyFormState.dirtyFields) {
1166
1165
  _formState.dirtyFields = getDirtyFields(_defaultValues, _formValues);
1167
1166
  }
1168
1167
  _subjects.state.next({
@@ -1176,10 +1175,10 @@ function createFormControl(props = {}) {
1176
1175
  _subjects.state.next({
1177
1176
  errors: _formState.errors,
1178
1177
  }));
1179
- const updateValidAndValue = (name, shouldSkipSetValueAs, ref) => {
1178
+ const updateValidAndValue = (name, shouldSkipSetValueAs, value, ref) => {
1180
1179
  const field = get(_fields, name);
1181
1180
  if (field) {
1182
- const defaultValue = get(_formValues, name, get(_defaultValues, name));
1181
+ const defaultValue = get(_formValues, name, isUndefined(value) ? get(_defaultValues, name) : value);
1183
1182
  isUndefined(defaultValue) ||
1184
1183
  (ref && ref.defaultChecked) ||
1185
1184
  shouldSkipSetValueAs
@@ -1188,7 +1187,7 @@ function createFormControl(props = {}) {
1188
1187
  _stateFlags.mount && _updateValid();
1189
1188
  }
1190
1189
  };
1191
- const updateTouchAndDirty = (name, fieldValue, isCurrentTouched, shouldRender = true) => {
1190
+ const updateTouchAndDirty = (name, fieldValue, isBlurEvent, shouldDirty, shouldRender) => {
1192
1191
  let isFieldDirty = false;
1193
1192
  const output = {
1194
1193
  name,
@@ -1199,7 +1198,7 @@ function createFormControl(props = {}) {
1199
1198
  _formState.isDirty = output.isDirty = _getDirty();
1200
1199
  isFieldDirty = isPreviousFormDirty !== output.isDirty;
1201
1200
  }
1202
- if (_proxyFormState.dirtyFields && !isCurrentTouched) {
1201
+ if (_proxyFormState.dirtyFields && (!isBlurEvent || shouldDirty)) {
1203
1202
  const isPreviousFieldDirty = get(_formState.dirtyFields, name);
1204
1203
  const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
1205
1204
  isCurrentFieldPristine
@@ -1210,13 +1209,13 @@ function createFormControl(props = {}) {
1210
1209
  isFieldDirty ||
1211
1210
  isPreviousFieldDirty !== get(_formState.dirtyFields, name);
1212
1211
  }
1213
- if (isCurrentTouched && !isPreviousFieldTouched) {
1214
- set(_formState.touchedFields, name, isCurrentTouched);
1212
+ if (isBlurEvent && !isPreviousFieldTouched) {
1213
+ set(_formState.touchedFields, name, isBlurEvent);
1215
1214
  output.touchedFields = _formState.touchedFields;
1216
1215
  isFieldDirty =
1217
1216
  isFieldDirty ||
1218
1217
  (_proxyFormState.touchedFields &&
1219
- isPreviousFieldTouched !== isCurrentTouched);
1218
+ isPreviousFieldTouched !== isBlurEvent);
1220
1219
  }
1221
1220
  isFieldDirty && shouldRender && _subjects.state.next(output);
1222
1221
  return isFieldDirty ? output : {};
@@ -1342,7 +1341,8 @@ function createFormControl(props = {}) {
1342
1341
  ? fieldReference.refs.forEach((checkboxRef) => (checkboxRef.checked = Array.isArray(fieldValue)
1343
1342
  ? !!fieldValue.find((data) => data === checkboxRef.value)
1344
1343
  : fieldValue === checkboxRef.value))
1345
- : (fieldReference.refs[0].checked = !!fieldValue);
1344
+ : fieldReference.refs[0] &&
1345
+ (fieldReference.refs[0].checked = !!fieldValue);
1346
1346
  }
1347
1347
  else {
1348
1348
  fieldReference.refs.forEach((radioRef) => (radioRef.checked = radioRef.value === fieldValue));
@@ -1359,7 +1359,7 @@ function createFormControl(props = {}) {
1359
1359
  }
1360
1360
  }
1361
1361
  (options.shouldDirty || options.shouldTouch) &&
1362
- updateTouchAndDirty(name, fieldValue, options.shouldTouch);
1362
+ updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty, true);
1363
1363
  options.shouldValidate && trigger(name);
1364
1364
  };
1365
1365
  const setValues = (name, value, options) => {
@@ -1378,7 +1378,8 @@ function createFormControl(props = {}) {
1378
1378
  const setValue = (name, value, options = {}) => {
1379
1379
  const field = get(_fields, name);
1380
1380
  const isFieldArray = _names.array.has(name);
1381
- set(_formValues, name, value);
1381
+ const cloneValue = cloneObject(value);
1382
+ set(_formValues, name, cloneValue);
1382
1383
  if (isFieldArray) {
1383
1384
  _subjects.array.next({
1384
1385
  name,
@@ -1390,14 +1391,14 @@ function createFormControl(props = {}) {
1390
1391
  _subjects.state.next({
1391
1392
  name,
1392
1393
  dirtyFields: _formState.dirtyFields,
1393
- isDirty: _getDirty(name, value),
1394
+ isDirty: _getDirty(name, cloneValue),
1394
1395
  });
1395
1396
  }
1396
1397
  }
1397
1398
  else {
1398
- field && !field._f && !isNullOrUndefined(value)
1399
- ? setValues(name, value, options)
1400
- : setFieldValue(name, value, options);
1399
+ field && !field._f && !isNullOrUndefined(cloneValue)
1400
+ ? setValues(name, cloneValue, options)
1401
+ : setFieldValue(name, cloneValue, options);
1401
1402
  }
1402
1403
  isWatched(name, _names) && _subjects.state.next({});
1403
1404
  _subjects.watch.next({
@@ -1421,13 +1422,13 @@ function createFormControl(props = {}) {
1421
1422
  !field._f.deps) ||
1422
1423
  skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, validationModeAfterSubmit, validationModeBeforeSubmit);
1423
1424
  const watched = isWatched(name, _names, isBlurEvent);
1425
+ set(_formValues, name, fieldValue);
1424
1426
  if (isBlurEvent) {
1425
1427
  field._f.onBlur && field._f.onBlur(event);
1426
1428
  }
1427
1429
  else if (field._f.onChange) {
1428
1430
  field._f.onChange(event);
1429
1431
  }
1430
- set(_formValues, name, fieldValue);
1431
1432
  const fieldState = updateTouchAndDirty(name, fieldValue, isBlurEvent, false);
1432
1433
  const shouldRender = !isEmptyObject(fieldState) || watched;
1433
1434
  !isBlurEvent &&
@@ -1502,13 +1503,18 @@ function createFormControl(props = {}) {
1502
1503
  ? get(values, fieldNames)
1503
1504
  : fieldNames.map((name) => get(values, name));
1504
1505
  };
1506
+ const _getFieldState = (name, formState) => ({
1507
+ invalid: !!get((formState || _formState).errors, name),
1508
+ isDirty: get((formState || _formState).dirtyFields, name),
1509
+ isTouched: get((formState || _formState).touchedFields, name),
1510
+ error: get((formState || _formState).errors, name),
1511
+ });
1505
1512
  const clearErrors = (name) => {
1506
1513
  name
1507
1514
  ? convertToArrayPayload(name).forEach((inputName) => unset(_formState.errors, inputName))
1508
1515
  : (_formState.errors = {});
1509
1516
  _subjects.state.next({
1510
1517
  errors: _formState.errors,
1511
- isValid: true,
1512
1518
  });
1513
1519
  };
1514
1520
  const setError = (name, error, options) => {
@@ -1549,20 +1555,18 @@ function createFormControl(props = {}) {
1549
1555
  };
1550
1556
  const register = (name, options = {}) => {
1551
1557
  let field = get(_fields, name);
1558
+ const disabledIsDefined = isBoolean(options.disabled);
1552
1559
  set(_fields, name, {
1553
1560
  _f: Object.assign(Object.assign(Object.assign({}, (field && field._f ? field._f : { ref: { name } })), { name, mount: true }), options),
1554
1561
  });
1555
1562
  _names.mount.add(name);
1556
- !isUndefined(options.value) &&
1557
- !options.disabled &&
1558
- set(_formValues, name, get(_formValues, name, options.value));
1559
1563
  field
1560
- ? isBoolean(options.disabled) &&
1564
+ ? disabledIsDefined &&
1561
1565
  set(_formValues, name, options.disabled
1562
1566
  ? undefined
1563
1567
  : get(_formValues, name, getFieldValue(field._f)))
1564
- : updateValidAndValue(name, true);
1565
- return Object.assign(Object.assign(Object.assign({}, (isBoolean(options.disabled) ? { disabled: options.disabled } : {})), (_options.shouldUseNativeValidation
1568
+ : updateValidAndValue(name, true, options.value);
1569
+ return Object.assign(Object.assign(Object.assign({}, (disabledIsDefined ? { disabled: options.disabled } : {})), (_options.shouldUseNativeValidation
1566
1570
  ? {
1567
1571
  required: !!options.required,
1568
1572
  min: getRuleValue(options.min),
@@ -1582,16 +1586,21 @@ function createFormControl(props = {}) {
1582
1586
  : ref
1583
1587
  : ref;
1584
1588
  const radioOrCheckbox = isRadioOrCheckbox(fieldRef);
1585
- if (fieldRef === field._f.ref ||
1586
- (radioOrCheckbox &&
1587
- compact(field._f.refs).find((option) => option === fieldRef))) {
1589
+ const refs = field._f.refs || [];
1590
+ if (radioOrCheckbox
1591
+ ? refs.find((option) => option === fieldRef)
1592
+ : fieldRef === field._f.ref) {
1588
1593
  return;
1589
1594
  }
1590
1595
  set(_fields, name, {
1591
- _f: radioOrCheckbox
1592
- ? Object.assign(Object.assign({}, field._f), { refs: [...compact(field._f.refs).filter(live), fieldRef], ref: { type: fieldRef.type, name } }) : Object.assign(Object.assign({}, field._f), { ref: fieldRef }),
1596
+ _f: Object.assign(Object.assign({}, field._f), (radioOrCheckbox
1597
+ ? {
1598
+ refs: refs.concat(fieldRef).filter(live),
1599
+ ref: { type: fieldRef.type, name },
1600
+ }
1601
+ : { ref: fieldRef })),
1593
1602
  });
1594
- updateValidAndValue(name, false, fieldRef);
1603
+ updateValidAndValue(name, false, undefined, fieldRef);
1595
1604
  }
1596
1605
  else {
1597
1606
  field = get(_fields, name, {});
@@ -1655,27 +1664,29 @@ function createFormControl(props = {}) {
1655
1664
  }
1656
1665
  };
1657
1666
  const resetField = (name, options = {}) => {
1658
- if (isUndefined(options.defaultValue)) {
1659
- setValue(name, get(_defaultValues, name));
1660
- }
1661
- else {
1662
- setValue(name, options.defaultValue);
1663
- set(_defaultValues, name, options.defaultValue);
1664
- }
1665
- if (!options.keepTouched) {
1666
- unset(_formState.touchedFields, name);
1667
- }
1668
- if (!options.keepDirty) {
1669
- unset(_formState.dirtyFields, name);
1670
- _formState.isDirty = options.defaultValue
1671
- ? _getDirty(name, get(_defaultValues, name))
1672
- : _getDirty();
1673
- }
1674
- if (!options.keepError) {
1675
- unset(_formState.errors, name);
1676
- _proxyFormState.isValid && _updateValid();
1667
+ if (get(_fields, name)) {
1668
+ if (isUndefined(options.defaultValue)) {
1669
+ setValue(name, get(_defaultValues, name));
1670
+ }
1671
+ else {
1672
+ setValue(name, options.defaultValue);
1673
+ set(_defaultValues, name, options.defaultValue);
1674
+ }
1675
+ if (!options.keepTouched) {
1676
+ unset(_formState.touchedFields, name);
1677
+ }
1678
+ if (!options.keepDirty) {
1679
+ unset(_formState.dirtyFields, name);
1680
+ _formState.isDirty = options.defaultValue
1681
+ ? _getDirty(name, get(_defaultValues, name))
1682
+ : _getDirty();
1683
+ }
1684
+ if (!options.keepError) {
1685
+ unset(_formState.errors, name);
1686
+ _proxyFormState.isValid && _updateValid();
1687
+ }
1688
+ _subjects.state.next(Object.assign({}, _formState));
1677
1689
  }
1678
- _subjects.state.next(Object.assign({}, _formState));
1679
1690
  };
1680
1691
  const reset = (formValues, keepStateOptions = {}) => {
1681
1692
  const updatedValues = formValues || _defaultValues;
@@ -1826,6 +1837,7 @@ function createFormControl(props = {}) {
1826
1837
  unregister,
1827
1838
  setError,
1828
1839
  setFocus,
1840
+ _getFieldState,
1829
1841
  };
1830
1842
  }
1831
1843