react-hook-form 6.9.2 → 6.9.5

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
@@ -36,27 +36,23 @@ function attachEventListeners({ ref }, shouldAttachChangeEvent, handleChange) {
36
36
 
37
37
  var isNullOrUndefined = (value) => value == null;
38
38
 
39
- var isArray = (value) => Array.isArray(value);
40
-
41
39
  const isObjectType = (value) => typeof value === 'object';
42
40
  var isObject = (value) => !isNullOrUndefined(value) &&
43
- !isArray(value) &&
41
+ !Array.isArray(value) &&
44
42
  isObjectType(value) &&
45
43
  !(value instanceof Date);
46
44
 
47
- var isKey = (value) => !isArray(value) &&
45
+ var isKey = (value) => !Array.isArray(value) &&
48
46
  (/^\w*$/.test(value) ||
49
47
  !/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/.test(value));
50
48
 
51
- var stringToPath = (input) => {
52
- const result = [];
53
- input.replace(/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g, (match, mathNumber, mathQuote, originalString) => {
54
- result.push(mathQuote
55
- ? originalString.replace(/\\(\\)?/g, '$1')
56
- : mathNumber || match);
57
- });
58
- return result;
59
- };
49
+ var compact = (value) => value.filter(Boolean);
50
+
51
+ var stringToPath = (input) => compact(input
52
+ .replace(/["|']/g, '')
53
+ .replace(/\[/g, '.')
54
+ .replace(/\]/g, '')
55
+ .split('.'));
60
56
 
61
57
  function set(object, path, value) {
62
58
  let index = -1;
@@ -69,7 +65,7 @@ function set(object, path, value) {
69
65
  if (index !== lastIndex) {
70
66
  const objValue = object[key];
71
67
  newValue =
72
- isObject(objValue) || isArray(objValue)
68
+ isObject(objValue) || Array.isArray(objValue)
73
69
  ? objValue
74
70
  : !isNaN(+tempPath[index + 1])
75
71
  ? []
@@ -81,20 +77,17 @@ function set(object, path, value) {
81
77
  return object;
82
78
  }
83
79
 
84
- var transformToNestObject = (data) => Object.entries(data).reduce((previous, [key, value]) => {
85
- if (!isKey(key)) {
86
- set(previous, key, value);
87
- return previous;
80
+ var transformToNestObject = (data, value = {}) => {
81
+ for (const key in data) {
82
+ !isKey(key) ? set(value, key, data[key]) : (value[key] = data[key]);
88
83
  }
89
- return Object.assign(Object.assign({}, previous), { [key]: value });
90
- }, {});
84
+ return value;
85
+ };
91
86
 
92
87
  var isUndefined = (val) => val === undefined;
93
88
 
94
- var filterOutFalsy = (value) => value.filter(Boolean);
95
-
96
89
  var get = (obj, path, defaultValue) => {
97
- const result = filterOutFalsy(path.split(/[,[\].]+?/)).reduce((result, key) => (isNullOrUndefined(result) ? result : result[key]), obj);
90
+ const result = compact(path.split(/[,[\].]+?/)).reduce((result, key) => (isNullOrUndefined(result) ? result : result[key]), obj);
98
91
  return isUndefined(result) || result === obj
99
92
  ? isUndefined(obj[path])
100
93
  ? defaultValue
@@ -132,7 +125,7 @@ const defaultReturn = {
132
125
  isValid: false,
133
126
  value: '',
134
127
  };
135
- var getRadioValue = (options) => isArray(options)
128
+ var getRadioValue = (options) => Array.isArray(options)
136
129
  ? options.reduce((previous, option) => option && option.ref.checked
137
130
  ? {
138
131
  isValid: true,
@@ -159,7 +152,7 @@ const defaultResult = {
159
152
  };
160
153
  const validResult = { value: true, isValid: true };
161
154
  var getCheckboxValue = (options) => {
162
- if (isArray(options)) {
155
+ if (Array.isArray(options)) {
163
156
  if (options.length > 1) {
164
157
  const values = options
165
158
  .filter((option) => option && option.ref.checked)
@@ -249,7 +242,7 @@ function unset(object, path) {
249
242
  objectRef = objectRef ? objectRef[item] : object[item];
250
243
  if (currentPathsLength === index &&
251
244
  ((isObject(objectRef) && isEmptyObject(objectRef)) ||
252
- (isArray(objectRef) &&
245
+ (Array.isArray(objectRef) &&
253
246
  !objectRef.filter((data) => (isObject(data) && !isEmptyObject(data)) || isBoolean(data)).length))) {
254
247
  previousObjRef ? delete previousObjRef[item] : delete object[item];
255
248
  }
@@ -275,15 +268,15 @@ function findRemovedFieldAndRemoveListener(fieldsRef, handleChange, field, shall
275
268
  }
276
269
  if ((isRadioInput(ref) || isCheckBoxInput(ref)) && fieldRef) {
277
270
  const { options } = fieldRef;
278
- if (isArray(options) && options.length) {
279
- filterOutFalsy(options).forEach((option, index) => {
271
+ if (Array.isArray(options) && options.length) {
272
+ compact(options).forEach((option, index) => {
280
273
  const { ref } = option;
281
274
  if ((ref && isDetached(ref) && isSameRef(option, ref)) || forceDelete) {
282
275
  removeAllEventListeners(ref, handleChange);
283
276
  unset(options, `[${index}]`);
284
277
  }
285
278
  });
286
- if (options && !filterOutFalsy(options).length) {
279
+ if (options && !compact(options).length) {
287
280
  delete fieldsRef.current[name];
288
281
  }
289
282
  }
@@ -301,7 +294,7 @@ function setFieldArrayDirtyFields(values, defaultValues, dirtyFields, parentNode
301
294
  let index = -1;
302
295
  while (++index < values.length) {
303
296
  for (const key in values[index]) {
304
- if (isArray(values[index][key])) {
297
+ if (Array.isArray(values[index][key])) {
305
298
  !dirtyFields[index] && (dirtyFields[index] = {});
306
299
  dirtyFields[index][key] = [];
307
300
  setFieldArrayDirtyFields(values[index][key], get(defaultValues[index] || {}, key, []), dirtyFields[index][key], dirtyFields[index], key);
@@ -331,13 +324,11 @@ function deepMerge(target, source) {
331
324
  const targetValue = target[key];
332
325
  const sourceValue = source[key];
333
326
  try {
334
- if ((isObject(targetValue) && isObject(sourceValue)) ||
335
- (isArray(targetValue) && isArray(sourceValue))) {
336
- target[key] = deepMerge(targetValue, sourceValue);
337
- }
338
- else {
339
- target[key] = sourceValue;
340
- }
327
+ target[key] =
328
+ (isObject(targetValue) && isObject(sourceValue)) ||
329
+ (Array.isArray(targetValue) && Array.isArray(sourceValue))
330
+ ? deepMerge(targetValue, sourceValue)
331
+ : sourceValue;
341
332
  }
342
333
  catch (_a) { }
343
334
  }
@@ -350,7 +341,7 @@ var getFieldsValues = (fieldsRef, shallowFieldsStateRef, excludeDisabled, search
350
341
  if (isUndefined(search) ||
351
342
  (isString(search)
352
343
  ? name.startsWith(search)
353
- : isArray(search) && search.find((data) => name.startsWith(data)))) {
344
+ : Array.isArray(search) && search.find((data) => name.startsWith(data)))) {
354
345
  output[name] = getFieldValue(fieldsRef, name, undefined, excludeDisabled);
355
346
  }
356
347
  }
@@ -367,7 +358,8 @@ function deepEqual(object1 = [], object2 = [], isErrorObject) {
367
358
  if (!(isErrorObject && ['ref', 'context'].includes(key))) {
368
359
  const val1 = object1[key];
369
360
  const val2 = object2[key];
370
- if ((isObject(val1) || isArray(val1)) && (isObject(val2) || isArray(val2))
361
+ if ((isObject(val1) || Array.isArray(val1)) &&
362
+ (isObject(val2) || Array.isArray(val2))
371
363
  ? !deepEqual(val1, val2, isErrorObject)
372
364
  : val1 !== val2) {
373
365
  return false;
@@ -559,7 +551,7 @@ var assignWatchFields = (fieldValues, fieldName, watchFields, inputValue, isSing
559
551
  }
560
552
  else {
561
553
  value = get(fieldValues, fieldName);
562
- if (isObject(value) || isArray(value)) {
554
+ if (isObject(value) || Array.isArray(value)) {
563
555
  getPath(fieldName, value).forEach((name) => watchFields.add(name));
564
556
  }
565
557
  }
@@ -615,6 +607,22 @@ function onDomRemove(fieldsRef, removeFieldEventListenerAndRef) {
615
607
  return observer;
616
608
  }
617
609
 
610
+ function cloneObject(object) {
611
+ let copy;
612
+ if (isPrimitive(object)) {
613
+ return object;
614
+ }
615
+ if (object instanceof Date) {
616
+ copy = new Date(object.getTime());
617
+ return copy;
618
+ }
619
+ copy = Array.isArray(object) ? [] : {};
620
+ for (const key in object) {
621
+ copy[key] = cloneObject(object[key]);
622
+ }
623
+ return copy;
624
+ }
625
+
618
626
  var modeChecker = (mode) => ({
619
627
  isOnSubmit: !mode || mode === VALIDATION_MODE.onSubmit,
620
628
  isOnBlur: mode === VALIDATION_MODE.onBlur,
@@ -643,7 +651,7 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
643
651
  const isUnMount = useRef(false);
644
652
  const isWatchAllRef = useRef(false);
645
653
  const handleChangeRef = useRef();
646
- const shallowFieldsStateRef = useRef(shouldUnregister ? {} : Object.assign({}, defaultValues));
654
+ const shallowFieldsStateRef = useRef(shouldUnregister ? {} : cloneObject(defaultValues));
647
655
  const resetFieldArrayFunctionRef = useRef({});
648
656
  const contextRef = useRef(context);
649
657
  const resolverRef = useRef(resolver);
@@ -723,7 +731,7 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
723
731
  }
724
732
  else if (isCheckBoxInput(ref) && options) {
725
733
  options.length > 1
726
- ? options.forEach(({ ref: checkboxRef }) => (checkboxRef.checked = isArray(value)
734
+ ? options.forEach(({ ref: checkboxRef }) => (checkboxRef.checked = Array.isArray(value)
727
735
  ? !!value.find((data) => data === checkboxRef.value)
728
736
  : value === checkboxRef.value))
729
737
  : (options[0].ref.checked = !!value);
@@ -734,7 +742,7 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
734
742
  }, []);
735
743
  const isFormDirty = () => !deepEqual(getValues(), isEmptyObject(defaultValuesRef.current)
736
744
  ? defaultValuesAtRenderRef.current
737
- : defaultValuesRef.current) || !isEmptyObject(formStateRef.current.dirtyFields);
745
+ : defaultValuesRef.current);
738
746
  const updateAndGetDirtyState = useCallback((name, shouldRender = true) => {
739
747
  if (readFormStateRef.current.isDirty ||
740
748
  readFormStateRef.current.dirtyFields) {
@@ -772,7 +780,7 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
772
780
  const executeSchemaOrResolverValidation = useCallback(async (names) => {
773
781
  const { errors } = await resolverRef.current(getValues(), contextRef.current, isValidateAllFieldCriteria);
774
782
  const previousFormIsValid = formStateRef.current.isValid;
775
- if (isArray(names)) {
783
+ if (Array.isArray(names)) {
776
784
  const isInputsValid = names
777
785
  .map((name) => {
778
786
  const error = get(errors, name);
@@ -799,7 +807,7 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
799
807
  if (resolverRef.current) {
800
808
  return executeSchemaOrResolverValidation(fields);
801
809
  }
802
- if (isArray(fields)) {
810
+ if (Array.isArray(fields)) {
803
811
  const result = await Promise.all(fields.map(async (data) => await executeValidation(data, null)));
804
812
  updateFormState();
805
813
  return result.every(Boolean);
@@ -829,8 +837,9 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
829
837
  resetFieldArrayFunctionRef.current[name]({
830
838
  [name]: value,
831
839
  });
832
- if (readFormStateRef.current.isDirty ||
833
- readFormStateRef.current.dirtyFields) {
840
+ if ((readFormStateRef.current.isDirty ||
841
+ readFormStateRef.current.dirtyFields) &&
842
+ config.shouldDirty) {
834
843
  set(formStateRef.current.dirtyFields, name, setFieldArrayDirtyFields(value, get(defaultValuesRef.current, name, []), get(formStateRef.current.dirtyFields, name, [])));
835
844
  updateFormState({
836
845
  isDirty: !deepEqual(Object.assign(Object.assign({}, getValues()), { [name]: value }), defaultValuesRef.current),
@@ -908,11 +917,13 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
908
917
  };
909
918
  function setFieldArrayDefaultValues(data) {
910
919
  if (!shouldUnregister) {
920
+ let copy = cloneObject(data);
911
921
  for (const value of fieldArrayNamesRef.current) {
912
- if (isKey(value) && !data[value]) {
913
- data = Object.assign(Object.assign({}, data), { [value]: [] });
922
+ if (isKey(value) && !copy[value]) {
923
+ copy = Object.assign(Object.assign({}, copy), { [value]: [] });
914
924
  }
915
925
  }
926
+ return copy;
916
927
  }
917
928
  return data;
918
929
  }
@@ -920,7 +931,7 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
920
931
  if (isString(payload)) {
921
932
  return getFieldValue(fieldsRef, payload, shallowFieldsStateRef);
922
933
  }
923
- if (isArray(payload)) {
934
+ if (Array.isArray(payload)) {
924
935
  const data = {};
925
936
  for (const name of payload) {
926
937
  set(data, name, getFieldValue(fieldsRef, name, shallowFieldsStateRef));
@@ -938,10 +949,26 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
938
949
  });
939
950
  }, [isValidateAllFieldCriteria]);
940
951
  const removeFieldEventListener = useCallback((field, forceDelete) => findRemovedFieldAndRemoveListener(fieldsRef, handleChangeRef.current, field, shallowFieldsStateRef, shouldUnregister, forceDelete), [shouldUnregister]);
952
+ const updateWatchedValue = (name) => {
953
+ if (isWatchAllRef.current) {
954
+ updateFormState();
955
+ }
956
+ else if (watchFieldsRef) {
957
+ let shouldRenderUseWatch = true;
958
+ for (const watchField of watchFieldsRef.current) {
959
+ if (watchField.startsWith(name)) {
960
+ updateFormState();
961
+ shouldRenderUseWatch = false;
962
+ break;
963
+ }
964
+ }
965
+ shouldRenderUseWatch && renderWatchedInputs(name);
966
+ }
967
+ };
941
968
  const removeFieldEventListenerAndRef = useCallback((field, forceDelete) => {
942
969
  if (field) {
943
970
  removeFieldEventListener(field, forceDelete);
944
- if (shouldUnregister && !filterOutFalsy(field.options || []).length) {
971
+ if (shouldUnregister && !compact(field.options || []).length) {
945
972
  unset(defaultValuesAtRenderRef.current, field.ref.name);
946
973
  unset(validFieldsRef.current, field.ref.name);
947
974
  unset(fieldsWithValidationRef.current, field.ref.name);
@@ -953,12 +980,13 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
953
980
  dirtyFields: formStateRef.current.dirtyFields,
954
981
  });
955
982
  resolverRef.current && validateResolver();
983
+ updateWatchedValue(field.ref.name);
956
984
  }
957
985
  }
958
986
  }, [validateResolver, removeFieldEventListener]);
959
987
  function clearErrors(name) {
960
988
  name &&
961
- (isArray(name) ? name : [name]).forEach((inputName) => fieldsRef.current[inputName]
989
+ (Array.isArray(name) ? name : [name]).forEach((inputName) => fieldsRef.current[inputName]
962
990
  ? isKey(inputName)
963
991
  ? delete formStateRef.current.errors[inputName]
964
992
  : set(formStateRef.current.errors, inputName, undefined)
@@ -989,7 +1017,7 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
989
1017
  ? get(combinedDefaultValues, fieldNames)
990
1018
  : defaultValue, true);
991
1019
  }
992
- if (isArray(fieldNames)) {
1020
+ if (Array.isArray(fieldNames)) {
993
1021
  return fieldNames.reduce((previous, name) => (Object.assign(Object.assign({}, previous), { [name]: assignWatchFields(fieldValues, name, watchFields, combinedDefaultValues) })), {});
994
1022
  }
995
1023
  isWatchAllRef.current = isUndefined(watchId);
@@ -1000,7 +1028,7 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
1000
1028
  return watchInternal(fieldNames, defaultValue);
1001
1029
  }
1002
1030
  function unregister(name) {
1003
- for (const fieldName of isArray(name) ? name : [name]) {
1031
+ for (const fieldName of Array.isArray(name) ? name : [name]) {
1004
1032
  removeFieldEventListenerAndRef(fieldsRef.current[fieldName], true);
1005
1033
  }
1006
1034
  }
@@ -1027,8 +1055,8 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
1027
1055
  let defaultValue;
1028
1056
  if (field &&
1029
1057
  (isRadioOrCheckbox
1030
- ? isArray(field.options) &&
1031
- filterOutFalsy(field.options).find((option) => {
1058
+ ? Array.isArray(field.options) &&
1059
+ compact(field.options).find((option) => {
1032
1060
  return value === option.ref.value && compareRef(option.ref);
1033
1061
  })
1034
1062
  : compareRef(field.ref))) {
@@ -1038,7 +1066,7 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
1038
1066
  if (type) {
1039
1067
  field = isRadioOrCheckbox
1040
1068
  ? Object.assign({ options: [
1041
- ...filterOutFalsy((field && field.options) || []),
1069
+ ...compact((field && field.options) || []),
1042
1070
  {
1043
1071
  ref,
1044
1072
  },
@@ -1108,16 +1136,14 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
1108
1136
  }
1109
1137
  let fieldErrors = {};
1110
1138
  let fieldValues = setFieldArrayDefaultValues(getFieldsValues(fieldsRef, shallowFieldsStateRef, true));
1111
- if (readFormStateRef.current.isSubmitting) {
1139
+ readFormStateRef.current.isSubmitting &&
1112
1140
  updateFormState({
1113
1141
  isSubmitting: true,
1114
1142
  });
1115
- }
1116
1143
  try {
1117
1144
  if (resolverRef.current) {
1118
1145
  const { errors, values } = await resolverRef.current(fieldValues, contextRef.current, isValidateAllFieldCriteria);
1119
- formStateRef.current.errors = errors;
1120
- fieldErrors = errors;
1146
+ formStateRef.current.errors = fieldErrors = errors;
1121
1147
  fieldValues = values;
1122
1148
  }
1123
1149
  else {
@@ -1186,7 +1212,7 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
1186
1212
  for (const field of Object.values(fieldsRef.current)) {
1187
1213
  if (field) {
1188
1214
  const { ref, options } = field;
1189
- const inputRef = isRadioOrCheckboxFunction(ref) && isArray(options)
1215
+ const inputRef = isRadioOrCheckboxFunction(ref) && Array.isArray(options)
1190
1216
  ? options[0].ref
1191
1217
  : ref;
1192
1218
  if (isHTMLElement(inputRef)) {
@@ -1200,21 +1226,21 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
1200
1226
  }
1201
1227
  }
1202
1228
  fieldsRef.current = {};
1203
- defaultValuesRef.current = Object.assign({}, (values || defaultValuesRef.current));
1204
- if (values) {
1205
- renderWatchedInputs('');
1206
- }
1207
- shallowFieldsStateRef.current = shouldUnregister ? {} : Object.assign({}, values) || {};
1229
+ defaultValuesRef.current = cloneObject(values || defaultValuesRef.current);
1230
+ values && renderWatchedInputs('');
1208
1231
  Object.values(resetFieldArrayFunctionRef.current).forEach((resetFieldArray) => isFunction(resetFieldArray) && resetFieldArray());
1232
+ shallowFieldsStateRef.current = shouldUnregister
1233
+ ? {}
1234
+ : cloneObject(values) || {};
1209
1235
  resetRefs(omitResetState);
1210
1236
  };
1211
- observerRef.current =
1212
- observerRef.current || !isWeb
1213
- ? observerRef.current
1214
- : onDomRemove(fieldsRef, removeFieldEventListenerAndRef);
1215
1237
  useEffect(() => {
1216
1238
  isUnMount.current = false;
1217
1239
  resolver && readFormStateRef.current.isValid && validateResolver();
1240
+ observerRef.current =
1241
+ observerRef.current || !isWeb
1242
+ ? observerRef.current
1243
+ : onDomRemove(fieldsRef, removeFieldEventListenerAndRef);
1218
1244
  return () => {
1219
1245
  isUnMount.current = true;
1220
1246
  observerRef.current && observerRef.current.disconnect();
@@ -1222,8 +1248,7 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
1222
1248
  if (process.env.NODE_ENV !== 'production') {
1223
1249
  return;
1224
1250
  }
1225
- fieldsRef.current &&
1226
- Object.values(fieldsRef.current).forEach((field) => removeFieldEventListenerAndRef(field, true));
1251
+ Object.values(fieldsRef.current).forEach((field) => removeFieldEventListenerAndRef(field, true));
1227
1252
  };
1228
1253
  }, [removeFieldEventListenerAndRef]);
1229
1254
  if (!resolver && readFormStateRef.current.isValid) {
@@ -1238,15 +1263,13 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
1238
1263
  register: useCallback(register, [defaultValuesRef.current]),
1239
1264
  unregister: useCallback(unregister, []),
1240
1265
  };
1241
- const control = Object.assign({ renderWatchedInputs,
1266
+ const control = Object.assign({ updateWatchedValue,
1242
1267
  shouldUnregister,
1243
1268
  removeFieldEventListener,
1244
1269
  watchInternal, mode: modeRef.current, reValidateMode: {
1245
1270
  isReValidateOnBlur,
1246
1271
  isReValidateOnChange,
1247
1272
  }, fieldsRef,
1248
- isWatchAllRef,
1249
- watchFieldsRef,
1250
1273
  resetFieldArrayFunctionRef,
1251
1274
  useWatchFieldsRef,
1252
1275
  useWatchRenderFunctionsRef,
@@ -1332,16 +1355,16 @@ function removeAtIndexes(data, index) {
1332
1355
  delete data[k];
1333
1356
  }
1334
1357
  }
1335
- return filterOutFalsy(data);
1358
+ return compact(data);
1336
1359
  }
1337
1360
  var removeArrayAt = (data, index) => isUndefined(index)
1338
1361
  ? []
1339
- : isArray(index)
1362
+ : Array.isArray(index)
1340
1363
  ? removeAtIndexes(data, index)
1341
1364
  : removeAt(data, index);
1342
1365
 
1343
1366
  var moveArrayAt = (data, from, to) => {
1344
- if (isArray(data)) {
1367
+ if (Array.isArray(data)) {
1345
1368
  if (isUndefined(data[to])) {
1346
1369
  data[to] = undefined;
1347
1370
  }
@@ -1358,18 +1381,18 @@ var swapArrayAt = (data, indexA, indexB) => {
1358
1381
  };
1359
1382
 
1360
1383
  function prepend(data, value) {
1361
- return [...(isArray(value) ? value : [value || undefined]), ...data];
1384
+ return [...(Array.isArray(value) ? value : [value || undefined]), ...data];
1362
1385
  }
1363
1386
 
1364
1387
  function insert(data, index, value) {
1365
1388
  return [
1366
1389
  ...data.slice(0, index),
1367
- ...(isArray(value) ? value : [value || undefined]),
1390
+ ...(Array.isArray(value) ? value : [value || undefined]),
1368
1391
  ...data.slice(index),
1369
1392
  ];
1370
1393
  }
1371
1394
 
1372
- var fillEmptyArray = (value) => isArray(value) ? Array(value.length).fill(undefined) : undefined;
1395
+ var fillEmptyArray = (value) => Array.isArray(value) ? Array(value.length).fill(undefined) : undefined;
1373
1396
 
1374
1397
  function mapValueToBoolean(value) {
1375
1398
  if (isObject(value)) {
@@ -1381,10 +1404,11 @@ function mapValueToBoolean(value) {
1381
1404
  }
1382
1405
  return [true];
1383
1406
  }
1384
- var filterBooleanArray = (value) => (isArray(value) ? value : [value]).map(mapValueToBoolean).flat();
1407
+ var fillBooleanArray = (value) => (Array.isArray(value) ? value : [value])
1408
+ .map(mapValueToBoolean)
1409
+ .flat();
1385
1410
 
1386
- const appendId = (value, keyName) => (Object.assign({ [keyName]: generateId() }, value));
1387
- const mapIds = (data, keyName) => (isArray(data) ? data : []).map((value) => appendId(value, keyName));
1411
+ const mapIds = (values, keyName) => values.map((value) => (Object.assign({ [keyName]: generateId() }, value)));
1388
1412
  const useFieldArray = ({ control, name, keyName = 'id', }) => {
1389
1413
  const methods = useFormContext();
1390
1414
  if (process.env.NODE_ENV !== 'production') {
@@ -1393,25 +1417,23 @@ const useFieldArray = ({ control, name, keyName = 'id', }) => {
1393
1417
  }
1394
1418
  }
1395
1419
  const focusIndexRef = useRef(-1);
1396
- const { isWatchAllRef, resetFieldArrayFunctionRef, fieldArrayNamesRef, fieldsRef, defaultValuesRef, removeFieldEventListener, formStateRef, formStateRef: { current: { dirtyFields, touched }, }, shallowFieldsStateRef, updateFormState, readFormStateRef, watchFieldsRef, validFieldsRef, fieldsWithValidationRef, fieldArrayDefaultValuesRef, validateResolver, renderWatchedInputs, getValues, shouldUnregister, } = control || methods.control;
1420
+ const { updateWatchedValue, resetFieldArrayFunctionRef, fieldArrayNamesRef, fieldsRef, defaultValuesRef, removeFieldEventListener, formStateRef, shallowFieldsStateRef, updateFormState, readFormStateRef, validFieldsRef, fieldsWithValidationRef, fieldArrayDefaultValuesRef, validateResolver, getValues, shouldUnregister, } = control || methods.control;
1397
1421
  const fieldArrayParentName = getFieldArrayParentName(name);
1398
- const getDefaultValues = () => [
1422
+ const memoizedDefaultValues = useRef([
1399
1423
  ...(get(fieldArrayDefaultValuesRef.current, fieldArrayParentName)
1400
1424
  ? get(fieldArrayDefaultValuesRef.current, name, [])
1401
1425
  : get(shouldUnregister
1402
1426
  ? defaultValuesRef.current
1403
1427
  : shallowFieldsStateRef.current, name, [])),
1404
- ];
1405
- const memoizedDefaultValues = useRef(getDefaultValues());
1428
+ ]);
1406
1429
  const [fields, setFields] = useState(mapIds(memoizedDefaultValues.current, keyName));
1407
1430
  const allFields = useRef(fields);
1408
- const getCurrentFieldsValues = () => get(getValues() || {}, name, allFields.current).map((item, index) => (Object.assign(Object.assign({}, allFields.current[index]), item)));
1431
+ const getCurrentFieldsValues = () => get(getValues(), name, allFields.current).map((item, index) => (Object.assign(Object.assign({}, allFields.current[index]), item)));
1409
1432
  allFields.current = fields;
1410
1433
  fieldArrayNamesRef.current.add(name);
1411
1434
  if (!get(fieldArrayDefaultValuesRef.current, fieldArrayParentName)) {
1412
1435
  set(fieldArrayDefaultValuesRef.current, fieldArrayParentName, get(defaultValuesRef.current, fieldArrayParentName));
1413
1436
  }
1414
- const appendValueWithKey = (values) => values.map((value) => appendId(value, keyName));
1415
1437
  const setFieldAndValidState = (fieldsValues) => {
1416
1438
  setFields(fieldsValues);
1417
1439
  if (readFormStateRef.current.isValid && validateResolver) {
@@ -1429,13 +1451,31 @@ const useFieldArray = ({ control, name, keyName = 'id', }) => {
1429
1451
  }), get(defaultValuesRef.current, name)));
1430
1452
  const resetFields = () => {
1431
1453
  for (const key in fieldsRef.current) {
1432
- if (isMatchFieldArrayName(key, name) && fieldsRef.current[key]) {
1454
+ isMatchFieldArrayName(key, name) &&
1433
1455
  removeFieldEventListener(fieldsRef.current[key], true);
1456
+ }
1457
+ };
1458
+ const cleanup = (ref) => !compact(get(ref, name, [])).length && unset(ref, name);
1459
+ const updateDirtyFieldsWithDefaultValues = (updatedFieldArrayValues) => {
1460
+ const defaultFieldArrayValues = get(defaultValuesRef.current, name, []);
1461
+ const updateDirtyFieldsBaseOnDefaultValues = (base, target) => {
1462
+ for (const key in base) {
1463
+ for (const innerKey in base[key]) {
1464
+ if (innerKey !== keyName &&
1465
+ (!target[key] ||
1466
+ !base[key] ||
1467
+ base[key][innerKey] !== target[key][innerKey])) {
1468
+ set(formStateRef.current.dirtyFields, `${name}[${key}]`, Object.assign(Object.assign({}, get(formStateRef.current.dirtyFields, `${name}[${key}]`, {})), { [innerKey]: true }));
1469
+ }
1470
+ }
1434
1471
  }
1472
+ };
1473
+ if (updatedFieldArrayValues) {
1474
+ updateDirtyFieldsBaseOnDefaultValues(defaultFieldArrayValues, updatedFieldArrayValues);
1475
+ updateDirtyFieldsBaseOnDefaultValues(updatedFieldArrayValues, defaultFieldArrayValues);
1435
1476
  }
1436
1477
  };
1437
- const cleanup = (ref) => !filterOutFalsy(get(ref, name, [])).length && unset(ref, name);
1438
- const batchStateUpdate = (method, args, isDirty = true, shouldSet = true, shouldUpdateValid = false) => {
1478
+ const batchStateUpdate = (method, args, updatedFieldValues, isDirty = true, shouldSet = true, shouldUpdateValid = false) => {
1439
1479
  if (get(shallowFieldsStateRef.current, name)) {
1440
1480
  const output = method(get(shallowFieldsStateRef.current, name), args.argA, args.argB);
1441
1481
  shouldSet && set(shallowFieldsStateRef.current, name, output);
@@ -1445,21 +1485,23 @@ const useFieldArray = ({ control, name, keyName = 'id', }) => {
1445
1485
  shouldSet && set(fieldArrayDefaultValuesRef.current, name, output);
1446
1486
  cleanup(fieldArrayDefaultValuesRef.current);
1447
1487
  }
1448
- if (isArray(get(formStateRef.current.errors, name))) {
1488
+ if (Array.isArray(get(formStateRef.current.errors, name))) {
1449
1489
  const output = method(get(formStateRef.current.errors, name), args.argA, args.argB);
1450
1490
  shouldSet && set(formStateRef.current.errors, name, output);
1451
1491
  cleanup(formStateRef.current.errors);
1452
1492
  }
1453
- if (readFormStateRef.current.touched && get(touched, name)) {
1454
- const output = method(get(touched, name), args.argA, args.argB);
1455
- shouldSet && set(touched, name, output);
1456
- cleanup(touched);
1493
+ if (readFormStateRef.current.touched &&
1494
+ get(formStateRef.current.touched, name)) {
1495
+ const output = method(get(formStateRef.current.touched, name), args.argA, args.argB);
1496
+ shouldSet && set(formStateRef.current.touched, name, output);
1497
+ cleanup(formStateRef.current.touched);
1457
1498
  }
1458
1499
  if (readFormStateRef.current.dirtyFields ||
1459
1500
  readFormStateRef.current.isDirty) {
1460
- const output = method(get(dirtyFields, name, []), args.argC, args.argD);
1461
- shouldSet && set(dirtyFields, name, output);
1462
- cleanup(dirtyFields);
1501
+ const output = method(get(formStateRef.current.dirtyFields, name, []), args.argC, args.argD);
1502
+ shouldSet && set(formStateRef.current.dirtyFields, name, output);
1503
+ updateDirtyFieldsWithDefaultValues(updatedFieldValues);
1504
+ cleanup(formStateRef.current.dirtyFields);
1463
1505
  }
1464
1506
  if (shouldUpdateValid &&
1465
1507
  readFormStateRef.current.isValid &&
@@ -1471,30 +1513,23 @@ const useFieldArray = ({ control, name, keyName = 'id', }) => {
1471
1513
  }
1472
1514
  updateFormState({
1473
1515
  errors: formStateRef.current.errors,
1474
- dirtyFields,
1516
+ dirtyFields: formStateRef.current.dirtyFields,
1475
1517
  isDirty,
1476
- touched,
1518
+ touched: formStateRef.current.touched,
1477
1519
  });
1478
1520
  };
1479
1521
  const append = (value, shouldFocus = true) => {
1480
- setFieldAndValidState([
1522
+ const updateFormValues = [
1481
1523
  ...allFields.current,
1482
- ...(isArray(value)
1483
- ? appendValueWithKey(value)
1484
- : [appendId(value, keyName)]),
1485
- ]);
1524
+ ...mapIds(Array.isArray(value) ? value : [value], keyName),
1525
+ ];
1526
+ setFieldAndValidState(updateFormValues);
1486
1527
  if (readFormStateRef.current.dirtyFields ||
1487
1528
  readFormStateRef.current.isDirty) {
1488
- const dirtyInputs = get(dirtyFields, name, []);
1489
- set(dirtyFields, name, [
1490
- ...(allFields.current.length > dirtyInputs.length
1491
- ? (fillEmptyArray(allFields.current) || []).map((_, index) => dirtyInputs[index])
1492
- : dirtyInputs),
1493
- ...filterBooleanArray(value),
1494
- ]);
1529
+ updateDirtyFieldsWithDefaultValues(updateFormValues);
1495
1530
  updateFormState({
1496
1531
  isDirty: true,
1497
- dirtyFields,
1532
+ dirtyFields: formStateRef.current.dirtyFields,
1498
1533
  });
1499
1534
  }
1500
1535
  if (!shouldUnregister) {
@@ -1507,34 +1542,37 @@ const useFieldArray = ({ control, name, keyName = 'id', }) => {
1507
1542
  };
1508
1543
  const prepend$1 = (value, shouldFocus = true) => {
1509
1544
  const emptyArray = fillEmptyArray(value);
1510
- setFieldAndValidState(prepend(getCurrentFieldsValues(), isArray(value) ? appendValueWithKey(value) : [appendId(value, keyName)]));
1545
+ const updatedFieldArrayValues = prepend(getCurrentFieldsValues(), mapIds(Array.isArray(value) ? value : [value], keyName));
1546
+ setFieldAndValidState(updatedFieldArrayValues);
1511
1547
  resetFields();
1512
1548
  batchStateUpdate(prepend, {
1513
1549
  argA: emptyArray,
1514
- argC: filterBooleanArray(value),
1515
- });
1550
+ argC: fillBooleanArray(value),
1551
+ }, updatedFieldArrayValues);
1516
1552
  focusIndexRef.current = shouldFocus ? 0 : -1;
1517
1553
  };
1518
1554
  const remove = (index) => {
1519
1555
  const fieldValues = getCurrentFieldsValues();
1520
- setFieldAndValidState(removeArrayAt(fieldValues, index));
1556
+ const updatedFieldValues = removeArrayAt(fieldValues, index);
1557
+ setFieldAndValidState(updatedFieldValues);
1521
1558
  resetFields();
1522
1559
  batchStateUpdate(removeArrayAt, {
1523
1560
  argA: index,
1524
1561
  argC: index,
1525
- }, getIsDirtyState(removeArrayAt(fieldValues, index)), true, true);
1562
+ }, updatedFieldValues, getIsDirtyState(removeArrayAt(fieldValues, index)), true, true);
1526
1563
  };
1527
1564
  const insert$1 = (index, value, shouldFocus = true) => {
1528
1565
  const emptyArray = fillEmptyArray(value);
1529
1566
  const fieldValues = getCurrentFieldsValues();
1530
- setFieldAndValidState(insert(fieldValues, index, isArray(value) ? appendValueWithKey(value) : [appendId(value, keyName)]));
1567
+ const updatedFieldArrayValues = insert(fieldValues, index, mapIds(Array.isArray(value) ? value : [value], keyName));
1568
+ setFieldAndValidState(updatedFieldArrayValues);
1531
1569
  resetFields();
1532
1570
  batchStateUpdate(insert, {
1533
1571
  argA: index,
1534
1572
  argB: emptyArray,
1535
1573
  argC: index,
1536
- argD: filterBooleanArray(value),
1537
- }, getIsDirtyState(insert(fieldValues, index)));
1574
+ argD: fillBooleanArray(value),
1575
+ }, updatedFieldArrayValues, getIsDirtyState(insert(fieldValues, index)));
1538
1576
  focusIndexRef.current = shouldFocus ? index : -1;
1539
1577
  };
1540
1578
  const swap = (indexA, indexB) => {
@@ -1547,7 +1585,7 @@ const useFieldArray = ({ control, name, keyName = 'id', }) => {
1547
1585
  argB: indexB,
1548
1586
  argC: indexA,
1549
1587
  argD: indexB,
1550
- }, getIsDirtyState(fieldValues), false);
1588
+ }, undefined, getIsDirtyState(fieldValues), false);
1551
1589
  };
1552
1590
  const move = (from, to) => {
1553
1591
  const fieldValues = getCurrentFieldsValues();
@@ -1559,7 +1597,7 @@ const useFieldArray = ({ control, name, keyName = 'id', }) => {
1559
1597
  argB: to,
1560
1598
  argC: from,
1561
1599
  argD: to,
1562
- }, getIsDirtyState(fieldValues), false);
1600
+ }, undefined, getIsDirtyState(fieldValues), false);
1563
1601
  };
1564
1602
  const reset = (data) => {
1565
1603
  resetFields();
@@ -1579,20 +1617,7 @@ const useFieldArray = ({ control, name, keyName = 'id', }) => {
1579
1617
  defaultValues.pop();
1580
1618
  set(fieldArrayDefaultValuesRef.current, name, defaultValues);
1581
1619
  }
1582
- if (isWatchAllRef.current) {
1583
- updateFormState();
1584
- }
1585
- else if (watchFieldsRef) {
1586
- let shouldRenderUseWatch = true;
1587
- for (const watchField of watchFieldsRef.current) {
1588
- if (watchField.startsWith(name)) {
1589
- updateFormState();
1590
- shouldRenderUseWatch = false;
1591
- break;
1592
- }
1593
- }
1594
- shouldRenderUseWatch && renderWatchedInputs(name);
1595
- }
1620
+ updateWatchedValue(name);
1596
1621
  if (focusIndexRef.current > -1) {
1597
1622
  for (const key in fieldsRef.current) {
1598
1623
  const field = fieldsRef.current[key];
@@ -1639,7 +1664,7 @@ function useWatch({ control, name, defaultValue, }) {
1639
1664
  const [value, setValue] = useState(isUndefined(defaultValue)
1640
1665
  ? isString(name)
1641
1666
  ? get(defaultValuesRef.current, name)
1642
- : isArray(name)
1667
+ : Array.isArray(name)
1643
1668
  ? name.reduce((previous, inputName) => (Object.assign(Object.assign({}, previous), { [inputName]: get(defaultValuesRef.current, inputName) })), {})
1644
1669
  : defaultValuesRef.current
1645
1670
  : defaultValue);
@@ -1647,7 +1672,10 @@ function useWatch({ control, name, defaultValue, }) {
1647
1672
  const defaultValueRef = useRef(defaultValue);
1648
1673
  const updateWatchValue = useCallback(() => {
1649
1674
  const value = watchInternal(name, defaultValueRef.current, idRef.current);
1650
- setValue(isObject(value) ? Object.assign({}, value) : isArray(value) ? [...value] : value);
1675
+ setValue(isObject(value)
1676
+ ? Object.assign({}, value) : Array.isArray(value)
1677
+ ? [...value]
1678
+ : value);
1651
1679
  }, [setValue, watchInternal, defaultValueRef, name, idRef]);
1652
1680
  useEffect(() => {
1653
1681
  if (process.env.NODE_ENV !== 'production') {
@@ -1734,9 +1762,7 @@ const Controller = (_a) => {
1734
1762
  }
1735
1763
  }
1736
1764
  }, [rules, name, register]);
1737
- useEffect(() => () => {
1738
- !isNameInFieldArray(fieldArrayNamesRef.current, name) && unregister(name);
1739
- }, [unregister, name, fieldArrayNamesRef]);
1765
+ useEffect(() => () => unregister(name), [unregister, name]);
1740
1766
  useEffect(() => {
1741
1767
  if (process.env.NODE_ENV !== 'production') {
1742
1768
  if (isUndefined(value)) {