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.
@@ -40,27 +40,23 @@ function attachEventListeners({ ref }, shouldAttachChangeEvent, handleChange) {
40
40
 
41
41
  var isNullOrUndefined = (value) => value == null;
42
42
 
43
- var isArray = (value) => Array.isArray(value);
44
-
45
43
  const isObjectType = (value) => typeof value === 'object';
46
44
  var isObject = (value) => !isNullOrUndefined(value) &&
47
- !isArray(value) &&
45
+ !Array.isArray(value) &&
48
46
  isObjectType(value) &&
49
47
  !(value instanceof Date);
50
48
 
51
- var isKey = (value) => !isArray(value) &&
49
+ var isKey = (value) => !Array.isArray(value) &&
52
50
  (/^\w*$/.test(value) ||
53
51
  !/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/.test(value));
54
52
 
55
- var stringToPath = (input) => {
56
- const result = [];
57
- input.replace(/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g, (match, mathNumber, mathQuote, originalString) => {
58
- result.push(mathQuote
59
- ? originalString.replace(/\\(\\)?/g, '$1')
60
- : mathNumber || match);
61
- });
62
- return result;
63
- };
53
+ var compact = (value) => value.filter(Boolean);
54
+
55
+ var stringToPath = (input) => compact(input
56
+ .replace(/["|']/g, '')
57
+ .replace(/\[/g, '.')
58
+ .replace(/\]/g, '')
59
+ .split('.'));
64
60
 
65
61
  function set(object, path, value) {
66
62
  let index = -1;
@@ -73,7 +69,7 @@ function set(object, path, value) {
73
69
  if (index !== lastIndex) {
74
70
  const objValue = object[key];
75
71
  newValue =
76
- isObject(objValue) || isArray(objValue)
72
+ isObject(objValue) || Array.isArray(objValue)
77
73
  ? objValue
78
74
  : !isNaN(+tempPath[index + 1])
79
75
  ? []
@@ -85,20 +81,17 @@ function set(object, path, value) {
85
81
  return object;
86
82
  }
87
83
 
88
- var transformToNestObject = (data) => Object.entries(data).reduce((previous, [key, value]) => {
89
- if (!isKey(key)) {
90
- set(previous, key, value);
91
- return previous;
84
+ var transformToNestObject = (data, value = {}) => {
85
+ for (const key in data) {
86
+ !isKey(key) ? set(value, key, data[key]) : (value[key] = data[key]);
92
87
  }
93
- return Object.assign(Object.assign({}, previous), { [key]: value });
94
- }, {});
88
+ return value;
89
+ };
95
90
 
96
91
  var isUndefined = (val) => val === undefined;
97
92
 
98
- var filterOutFalsy = (value) => value.filter(Boolean);
99
-
100
93
  var get = (obj, path, defaultValue) => {
101
- const result = filterOutFalsy(path.split(/[,[\].]+?/)).reduce((result, key) => (isNullOrUndefined(result) ? result : result[key]), obj);
94
+ const result = compact(path.split(/[,[\].]+?/)).reduce((result, key) => (isNullOrUndefined(result) ? result : result[key]), obj);
102
95
  return isUndefined(result) || result === obj
103
96
  ? isUndefined(obj[path])
104
97
  ? defaultValue
@@ -136,7 +129,7 @@ const defaultReturn = {
136
129
  isValid: false,
137
130
  value: '',
138
131
  };
139
- var getRadioValue = (options) => isArray(options)
132
+ var getRadioValue = (options) => Array.isArray(options)
140
133
  ? options.reduce((previous, option) => option && option.ref.checked
141
134
  ? {
142
135
  isValid: true,
@@ -163,7 +156,7 @@ const defaultResult = {
163
156
  };
164
157
  const validResult = { value: true, isValid: true };
165
158
  var getCheckboxValue = (options) => {
166
- if (isArray(options)) {
159
+ if (Array.isArray(options)) {
167
160
  if (options.length > 1) {
168
161
  const values = options
169
162
  .filter((option) => option && option.ref.checked)
@@ -253,7 +246,7 @@ function unset(object, path) {
253
246
  objectRef = objectRef ? objectRef[item] : object[item];
254
247
  if (currentPathsLength === index &&
255
248
  ((isObject(objectRef) && isEmptyObject(objectRef)) ||
256
- (isArray(objectRef) &&
249
+ (Array.isArray(objectRef) &&
257
250
  !objectRef.filter((data) => (isObject(data) && !isEmptyObject(data)) || isBoolean(data)).length))) {
258
251
  previousObjRef ? delete previousObjRef[item] : delete object[item];
259
252
  }
@@ -279,15 +272,15 @@ function findRemovedFieldAndRemoveListener(fieldsRef, handleChange, field, shall
279
272
  }
280
273
  if ((isRadioInput(ref) || isCheckBoxInput(ref)) && fieldRef) {
281
274
  const { options } = fieldRef;
282
- if (isArray(options) && options.length) {
283
- filterOutFalsy(options).forEach((option, index) => {
275
+ if (Array.isArray(options) && options.length) {
276
+ compact(options).forEach((option, index) => {
284
277
  const { ref } = option;
285
278
  if ((ref && isDetached(ref) && isSameRef(option, ref)) || forceDelete) {
286
279
  removeAllEventListeners(ref, handleChange);
287
280
  unset(options, `[${index}]`);
288
281
  }
289
282
  });
290
- if (options && !filterOutFalsy(options).length) {
283
+ if (options && !compact(options).length) {
291
284
  delete fieldsRef.current[name];
292
285
  }
293
286
  }
@@ -305,7 +298,7 @@ function setFieldArrayDirtyFields(values, defaultValues, dirtyFields, parentNode
305
298
  let index = -1;
306
299
  while (++index < values.length) {
307
300
  for (const key in values[index]) {
308
- if (isArray(values[index][key])) {
301
+ if (Array.isArray(values[index][key])) {
309
302
  !dirtyFields[index] && (dirtyFields[index] = {});
310
303
  dirtyFields[index][key] = [];
311
304
  setFieldArrayDirtyFields(values[index][key], get(defaultValues[index] || {}, key, []), dirtyFields[index][key], dirtyFields[index], key);
@@ -335,13 +328,11 @@ function deepMerge(target, source) {
335
328
  const targetValue = target[key];
336
329
  const sourceValue = source[key];
337
330
  try {
338
- if ((isObject(targetValue) && isObject(sourceValue)) ||
339
- (isArray(targetValue) && isArray(sourceValue))) {
340
- target[key] = deepMerge(targetValue, sourceValue);
341
- }
342
- else {
343
- target[key] = sourceValue;
344
- }
331
+ target[key] =
332
+ (isObject(targetValue) && isObject(sourceValue)) ||
333
+ (Array.isArray(targetValue) && Array.isArray(sourceValue))
334
+ ? deepMerge(targetValue, sourceValue)
335
+ : sourceValue;
345
336
  }
346
337
  catch (_a) { }
347
338
  }
@@ -354,7 +345,7 @@ var getFieldsValues = (fieldsRef, shallowFieldsStateRef, excludeDisabled, search
354
345
  if (isUndefined(search) ||
355
346
  (isString(search)
356
347
  ? name.startsWith(search)
357
- : isArray(search) && search.find((data) => name.startsWith(data)))) {
348
+ : Array.isArray(search) && search.find((data) => name.startsWith(data)))) {
358
349
  output[name] = getFieldValue(fieldsRef, name, undefined, excludeDisabled);
359
350
  }
360
351
  }
@@ -371,7 +362,8 @@ function deepEqual(object1 = [], object2 = [], isErrorObject) {
371
362
  if (!(isErrorObject && ['ref', 'context'].includes(key))) {
372
363
  const val1 = object1[key];
373
364
  const val2 = object2[key];
374
- if ((isObject(val1) || isArray(val1)) && (isObject(val2) || isArray(val2))
365
+ if ((isObject(val1) || Array.isArray(val1)) &&
366
+ (isObject(val2) || Array.isArray(val2))
375
367
  ? !deepEqual(val1, val2, isErrorObject)
376
368
  : val1 !== val2) {
377
369
  return false;
@@ -563,7 +555,7 @@ var assignWatchFields = (fieldValues, fieldName, watchFields, inputValue, isSing
563
555
  }
564
556
  else {
565
557
  value = get(fieldValues, fieldName);
566
- if (isObject(value) || isArray(value)) {
558
+ if (isObject(value) || Array.isArray(value)) {
567
559
  getPath(fieldName, value).forEach((name) => watchFields.add(name));
568
560
  }
569
561
  }
@@ -619,6 +611,22 @@ function onDomRemove(fieldsRef, removeFieldEventListenerAndRef) {
619
611
  return observer;
620
612
  }
621
613
 
614
+ function cloneObject(object) {
615
+ let copy;
616
+ if (isPrimitive(object)) {
617
+ return object;
618
+ }
619
+ if (object instanceof Date) {
620
+ copy = new Date(object.getTime());
621
+ return copy;
622
+ }
623
+ copy = Array.isArray(object) ? [] : {};
624
+ for (const key in object) {
625
+ copy[key] = cloneObject(object[key]);
626
+ }
627
+ return copy;
628
+ }
629
+
622
630
  var modeChecker = (mode) => ({
623
631
  isOnSubmit: !mode || mode === VALIDATION_MODE.onSubmit,
624
632
  isOnBlur: mode === VALIDATION_MODE.onBlur,
@@ -647,7 +655,7 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
647
655
  const isUnMount = React.useRef(false);
648
656
  const isWatchAllRef = React.useRef(false);
649
657
  const handleChangeRef = React.useRef();
650
- const shallowFieldsStateRef = React.useRef(shouldUnregister ? {} : Object.assign({}, defaultValues));
658
+ const shallowFieldsStateRef = React.useRef(shouldUnregister ? {} : cloneObject(defaultValues));
651
659
  const resetFieldArrayFunctionRef = React.useRef({});
652
660
  const contextRef = React.useRef(context);
653
661
  const resolverRef = React.useRef(resolver);
@@ -727,7 +735,7 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
727
735
  }
728
736
  else if (isCheckBoxInput(ref) && options) {
729
737
  options.length > 1
730
- ? options.forEach(({ ref: checkboxRef }) => (checkboxRef.checked = isArray(value)
738
+ ? options.forEach(({ ref: checkboxRef }) => (checkboxRef.checked = Array.isArray(value)
731
739
  ? !!value.find((data) => data === checkboxRef.value)
732
740
  : value === checkboxRef.value))
733
741
  : (options[0].ref.checked = !!value);
@@ -738,7 +746,7 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
738
746
  }, []);
739
747
  const isFormDirty = () => !deepEqual(getValues(), isEmptyObject(defaultValuesRef.current)
740
748
  ? defaultValuesAtRenderRef.current
741
- : defaultValuesRef.current) || !isEmptyObject(formStateRef.current.dirtyFields);
749
+ : defaultValuesRef.current);
742
750
  const updateAndGetDirtyState = React.useCallback((name, shouldRender = true) => {
743
751
  if (readFormStateRef.current.isDirty ||
744
752
  readFormStateRef.current.dirtyFields) {
@@ -776,7 +784,7 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
776
784
  const executeSchemaOrResolverValidation = React.useCallback(async (names) => {
777
785
  const { errors } = await resolverRef.current(getValues(), contextRef.current, isValidateAllFieldCriteria);
778
786
  const previousFormIsValid = formStateRef.current.isValid;
779
- if (isArray(names)) {
787
+ if (Array.isArray(names)) {
780
788
  const isInputsValid = names
781
789
  .map((name) => {
782
790
  const error = get(errors, name);
@@ -803,7 +811,7 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
803
811
  if (resolverRef.current) {
804
812
  return executeSchemaOrResolverValidation(fields);
805
813
  }
806
- if (isArray(fields)) {
814
+ if (Array.isArray(fields)) {
807
815
  const result = await Promise.all(fields.map(async (data) => await executeValidation(data, null)));
808
816
  updateFormState();
809
817
  return result.every(Boolean);
@@ -833,8 +841,9 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
833
841
  resetFieldArrayFunctionRef.current[name]({
834
842
  [name]: value,
835
843
  });
836
- if (readFormStateRef.current.isDirty ||
837
- readFormStateRef.current.dirtyFields) {
844
+ if ((readFormStateRef.current.isDirty ||
845
+ readFormStateRef.current.dirtyFields) &&
846
+ config.shouldDirty) {
838
847
  set(formStateRef.current.dirtyFields, name, setFieldArrayDirtyFields(value, get(defaultValuesRef.current, name, []), get(formStateRef.current.dirtyFields, name, [])));
839
848
  updateFormState({
840
849
  isDirty: !deepEqual(Object.assign(Object.assign({}, getValues()), { [name]: value }), defaultValuesRef.current),
@@ -912,11 +921,13 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
912
921
  };
913
922
  function setFieldArrayDefaultValues(data) {
914
923
  if (!shouldUnregister) {
924
+ let copy = cloneObject(data);
915
925
  for (const value of fieldArrayNamesRef.current) {
916
- if (isKey(value) && !data[value]) {
917
- data = Object.assign(Object.assign({}, data), { [value]: [] });
926
+ if (isKey(value) && !copy[value]) {
927
+ copy = Object.assign(Object.assign({}, copy), { [value]: [] });
918
928
  }
919
929
  }
930
+ return copy;
920
931
  }
921
932
  return data;
922
933
  }
@@ -924,7 +935,7 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
924
935
  if (isString(payload)) {
925
936
  return getFieldValue(fieldsRef, payload, shallowFieldsStateRef);
926
937
  }
927
- if (isArray(payload)) {
938
+ if (Array.isArray(payload)) {
928
939
  const data = {};
929
940
  for (const name of payload) {
930
941
  set(data, name, getFieldValue(fieldsRef, name, shallowFieldsStateRef));
@@ -942,10 +953,26 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
942
953
  });
943
954
  }, [isValidateAllFieldCriteria]);
944
955
  const removeFieldEventListener = React.useCallback((field, forceDelete) => findRemovedFieldAndRemoveListener(fieldsRef, handleChangeRef.current, field, shallowFieldsStateRef, shouldUnregister, forceDelete), [shouldUnregister]);
956
+ const updateWatchedValue = (name) => {
957
+ if (isWatchAllRef.current) {
958
+ updateFormState();
959
+ }
960
+ else if (watchFieldsRef) {
961
+ let shouldRenderUseWatch = true;
962
+ for (const watchField of watchFieldsRef.current) {
963
+ if (watchField.startsWith(name)) {
964
+ updateFormState();
965
+ shouldRenderUseWatch = false;
966
+ break;
967
+ }
968
+ }
969
+ shouldRenderUseWatch && renderWatchedInputs(name);
970
+ }
971
+ };
945
972
  const removeFieldEventListenerAndRef = React.useCallback((field, forceDelete) => {
946
973
  if (field) {
947
974
  removeFieldEventListener(field, forceDelete);
948
- if (shouldUnregister && !filterOutFalsy(field.options || []).length) {
975
+ if (shouldUnregister && !compact(field.options || []).length) {
949
976
  unset(defaultValuesAtRenderRef.current, field.ref.name);
950
977
  unset(validFieldsRef.current, field.ref.name);
951
978
  unset(fieldsWithValidationRef.current, field.ref.name);
@@ -957,12 +984,13 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
957
984
  dirtyFields: formStateRef.current.dirtyFields,
958
985
  });
959
986
  resolverRef.current && validateResolver();
987
+ updateWatchedValue(field.ref.name);
960
988
  }
961
989
  }
962
990
  }, [validateResolver, removeFieldEventListener]);
963
991
  function clearErrors(name) {
964
992
  name &&
965
- (isArray(name) ? name : [name]).forEach((inputName) => fieldsRef.current[inputName]
993
+ (Array.isArray(name) ? name : [name]).forEach((inputName) => fieldsRef.current[inputName]
966
994
  ? isKey(inputName)
967
995
  ? delete formStateRef.current.errors[inputName]
968
996
  : set(formStateRef.current.errors, inputName, undefined)
@@ -993,7 +1021,7 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
993
1021
  ? get(combinedDefaultValues, fieldNames)
994
1022
  : defaultValue, true);
995
1023
  }
996
- if (isArray(fieldNames)) {
1024
+ if (Array.isArray(fieldNames)) {
997
1025
  return fieldNames.reduce((previous, name) => (Object.assign(Object.assign({}, previous), { [name]: assignWatchFields(fieldValues, name, watchFields, combinedDefaultValues) })), {});
998
1026
  }
999
1027
  isWatchAllRef.current = isUndefined(watchId);
@@ -1004,7 +1032,7 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
1004
1032
  return watchInternal(fieldNames, defaultValue);
1005
1033
  }
1006
1034
  function unregister(name) {
1007
- for (const fieldName of isArray(name) ? name : [name]) {
1035
+ for (const fieldName of Array.isArray(name) ? name : [name]) {
1008
1036
  removeFieldEventListenerAndRef(fieldsRef.current[fieldName], true);
1009
1037
  }
1010
1038
  }
@@ -1031,8 +1059,8 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
1031
1059
  let defaultValue;
1032
1060
  if (field &&
1033
1061
  (isRadioOrCheckbox
1034
- ? isArray(field.options) &&
1035
- filterOutFalsy(field.options).find((option) => {
1062
+ ? Array.isArray(field.options) &&
1063
+ compact(field.options).find((option) => {
1036
1064
  return value === option.ref.value && compareRef(option.ref);
1037
1065
  })
1038
1066
  : compareRef(field.ref))) {
@@ -1042,7 +1070,7 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
1042
1070
  if (type) {
1043
1071
  field = isRadioOrCheckbox
1044
1072
  ? Object.assign({ options: [
1045
- ...filterOutFalsy((field && field.options) || []),
1073
+ ...compact((field && field.options) || []),
1046
1074
  {
1047
1075
  ref,
1048
1076
  },
@@ -1112,16 +1140,14 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
1112
1140
  }
1113
1141
  let fieldErrors = {};
1114
1142
  let fieldValues = setFieldArrayDefaultValues(getFieldsValues(fieldsRef, shallowFieldsStateRef, true));
1115
- if (readFormStateRef.current.isSubmitting) {
1143
+ readFormStateRef.current.isSubmitting &&
1116
1144
  updateFormState({
1117
1145
  isSubmitting: true,
1118
1146
  });
1119
- }
1120
1147
  try {
1121
1148
  if (resolverRef.current) {
1122
1149
  const { errors, values } = await resolverRef.current(fieldValues, contextRef.current, isValidateAllFieldCriteria);
1123
- formStateRef.current.errors = errors;
1124
- fieldErrors = errors;
1150
+ formStateRef.current.errors = fieldErrors = errors;
1125
1151
  fieldValues = values;
1126
1152
  }
1127
1153
  else {
@@ -1190,7 +1216,7 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
1190
1216
  for (const field of Object.values(fieldsRef.current)) {
1191
1217
  if (field) {
1192
1218
  const { ref, options } = field;
1193
- const inputRef = isRadioOrCheckboxFunction(ref) && isArray(options)
1219
+ const inputRef = isRadioOrCheckboxFunction(ref) && Array.isArray(options)
1194
1220
  ? options[0].ref
1195
1221
  : ref;
1196
1222
  if (isHTMLElement(inputRef)) {
@@ -1204,21 +1230,21 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
1204
1230
  }
1205
1231
  }
1206
1232
  fieldsRef.current = {};
1207
- defaultValuesRef.current = Object.assign({}, (values || defaultValuesRef.current));
1208
- if (values) {
1209
- renderWatchedInputs('');
1210
- }
1211
- shallowFieldsStateRef.current = shouldUnregister ? {} : Object.assign({}, values) || {};
1233
+ defaultValuesRef.current = cloneObject(values || defaultValuesRef.current);
1234
+ values && renderWatchedInputs('');
1212
1235
  Object.values(resetFieldArrayFunctionRef.current).forEach((resetFieldArray) => isFunction(resetFieldArray) && resetFieldArray());
1236
+ shallowFieldsStateRef.current = shouldUnregister
1237
+ ? {}
1238
+ : cloneObject(values) || {};
1213
1239
  resetRefs(omitResetState);
1214
1240
  };
1215
- observerRef.current =
1216
- observerRef.current || !isWeb
1217
- ? observerRef.current
1218
- : onDomRemove(fieldsRef, removeFieldEventListenerAndRef);
1219
1241
  React.useEffect(() => {
1220
1242
  isUnMount.current = false;
1221
1243
  resolver && readFormStateRef.current.isValid && validateResolver();
1244
+ observerRef.current =
1245
+ observerRef.current || !isWeb
1246
+ ? observerRef.current
1247
+ : onDomRemove(fieldsRef, removeFieldEventListenerAndRef);
1222
1248
  return () => {
1223
1249
  isUnMount.current = true;
1224
1250
  observerRef.current && observerRef.current.disconnect();
@@ -1240,15 +1266,13 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
1240
1266
  register: React.useCallback(register, [defaultValuesRef.current]),
1241
1267
  unregister: React.useCallback(unregister, []),
1242
1268
  };
1243
- const control = Object.assign({ renderWatchedInputs,
1269
+ const control = Object.assign({ updateWatchedValue,
1244
1270
  shouldUnregister,
1245
1271
  removeFieldEventListener,
1246
1272
  watchInternal, mode: modeRef.current, reValidateMode: {
1247
1273
  isReValidateOnBlur,
1248
1274
  isReValidateOnChange,
1249
1275
  }, fieldsRef,
1250
- isWatchAllRef,
1251
- watchFieldsRef,
1252
1276
  resetFieldArrayFunctionRef,
1253
1277
  useWatchFieldsRef,
1254
1278
  useWatchRenderFunctionsRef,
@@ -1334,16 +1358,16 @@ function removeAtIndexes(data, index) {
1334
1358
  delete data[k];
1335
1359
  }
1336
1360
  }
1337
- return filterOutFalsy(data);
1361
+ return compact(data);
1338
1362
  }
1339
1363
  var removeArrayAt = (data, index) => isUndefined(index)
1340
1364
  ? []
1341
- : isArray(index)
1365
+ : Array.isArray(index)
1342
1366
  ? removeAtIndexes(data, index)
1343
1367
  : removeAt(data, index);
1344
1368
 
1345
1369
  var moveArrayAt = (data, from, to) => {
1346
- if (isArray(data)) {
1370
+ if (Array.isArray(data)) {
1347
1371
  if (isUndefined(data[to])) {
1348
1372
  data[to] = undefined;
1349
1373
  }
@@ -1360,18 +1384,18 @@ var swapArrayAt = (data, indexA, indexB) => {
1360
1384
  };
1361
1385
 
1362
1386
  function prepend(data, value) {
1363
- return [...(isArray(value) ? value : [value || undefined]), ...data];
1387
+ return [...(Array.isArray(value) ? value : [value || undefined]), ...data];
1364
1388
  }
1365
1389
 
1366
1390
  function insert(data, index, value) {
1367
1391
  return [
1368
1392
  ...data.slice(0, index),
1369
- ...(isArray(value) ? value : [value || undefined]),
1393
+ ...(Array.isArray(value) ? value : [value || undefined]),
1370
1394
  ...data.slice(index),
1371
1395
  ];
1372
1396
  }
1373
1397
 
1374
- var fillEmptyArray = (value) => isArray(value) ? Array(value.length).fill(undefined) : undefined;
1398
+ var fillEmptyArray = (value) => Array.isArray(value) ? Array(value.length).fill(undefined) : undefined;
1375
1399
 
1376
1400
  function mapValueToBoolean(value) {
1377
1401
  if (isObject(value)) {
@@ -1383,10 +1407,11 @@ function mapValueToBoolean(value) {
1383
1407
  }
1384
1408
  return [true];
1385
1409
  }
1386
- var filterBooleanArray = (value) => (isArray(value) ? value : [value]).map(mapValueToBoolean).flat();
1410
+ var fillBooleanArray = (value) => (Array.isArray(value) ? value : [value])
1411
+ .map(mapValueToBoolean)
1412
+ .flat();
1387
1413
 
1388
- const appendId = (value, keyName) => (Object.assign({ [keyName]: generateId() }, value));
1389
- const mapIds = (data, keyName) => (isArray(data) ? data : []).map((value) => appendId(value, keyName));
1414
+ const mapIds = (values, keyName) => values.map((value) => (Object.assign({ [keyName]: generateId() }, value)));
1390
1415
  const useFieldArray = ({ control, name, keyName = 'id', }) => {
1391
1416
  const methods = useFormContext();
1392
1417
  {
@@ -1395,25 +1420,23 @@ const useFieldArray = ({ control, name, keyName = 'id', }) => {
1395
1420
  }
1396
1421
  }
1397
1422
  const focusIndexRef = React.useRef(-1);
1398
- 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;
1423
+ const { updateWatchedValue, resetFieldArrayFunctionRef, fieldArrayNamesRef, fieldsRef, defaultValuesRef, removeFieldEventListener, formStateRef, shallowFieldsStateRef, updateFormState, readFormStateRef, validFieldsRef, fieldsWithValidationRef, fieldArrayDefaultValuesRef, validateResolver, getValues, shouldUnregister, } = control || methods.control;
1399
1424
  const fieldArrayParentName = getFieldArrayParentName(name);
1400
- const getDefaultValues = () => [
1425
+ const memoizedDefaultValues = React.useRef([
1401
1426
  ...(get(fieldArrayDefaultValuesRef.current, fieldArrayParentName)
1402
1427
  ? get(fieldArrayDefaultValuesRef.current, name, [])
1403
1428
  : get(shouldUnregister
1404
1429
  ? defaultValuesRef.current
1405
1430
  : shallowFieldsStateRef.current, name, [])),
1406
- ];
1407
- const memoizedDefaultValues = React.useRef(getDefaultValues());
1431
+ ]);
1408
1432
  const [fields, setFields] = React.useState(mapIds(memoizedDefaultValues.current, keyName));
1409
1433
  const allFields = React.useRef(fields);
1410
- const getCurrentFieldsValues = () => get(getValues() || {}, name, allFields.current).map((item, index) => (Object.assign(Object.assign({}, allFields.current[index]), item)));
1434
+ const getCurrentFieldsValues = () => get(getValues(), name, allFields.current).map((item, index) => (Object.assign(Object.assign({}, allFields.current[index]), item)));
1411
1435
  allFields.current = fields;
1412
1436
  fieldArrayNamesRef.current.add(name);
1413
1437
  if (!get(fieldArrayDefaultValuesRef.current, fieldArrayParentName)) {
1414
1438
  set(fieldArrayDefaultValuesRef.current, fieldArrayParentName, get(defaultValuesRef.current, fieldArrayParentName));
1415
1439
  }
1416
- const appendValueWithKey = (values) => values.map((value) => appendId(value, keyName));
1417
1440
  const setFieldAndValidState = (fieldsValues) => {
1418
1441
  setFields(fieldsValues);
1419
1442
  if (readFormStateRef.current.isValid && validateResolver) {
@@ -1431,13 +1454,31 @@ const useFieldArray = ({ control, name, keyName = 'id', }) => {
1431
1454
  }), get(defaultValuesRef.current, name)));
1432
1455
  const resetFields = () => {
1433
1456
  for (const key in fieldsRef.current) {
1434
- if (isMatchFieldArrayName(key, name) && fieldsRef.current[key]) {
1457
+ isMatchFieldArrayName(key, name) &&
1435
1458
  removeFieldEventListener(fieldsRef.current[key], true);
1459
+ }
1460
+ };
1461
+ const cleanup = (ref) => !compact(get(ref, name, [])).length && unset(ref, name);
1462
+ const updateDirtyFieldsWithDefaultValues = (updatedFieldArrayValues) => {
1463
+ const defaultFieldArrayValues = get(defaultValuesRef.current, name, []);
1464
+ const updateDirtyFieldsBaseOnDefaultValues = (base, target) => {
1465
+ for (const key in base) {
1466
+ for (const innerKey in base[key]) {
1467
+ if (innerKey !== keyName &&
1468
+ (!target[key] ||
1469
+ !base[key] ||
1470
+ base[key][innerKey] !== target[key][innerKey])) {
1471
+ set(formStateRef.current.dirtyFields, `${name}[${key}]`, Object.assign(Object.assign({}, get(formStateRef.current.dirtyFields, `${name}[${key}]`, {})), { [innerKey]: true }));
1472
+ }
1473
+ }
1436
1474
  }
1475
+ };
1476
+ if (updatedFieldArrayValues) {
1477
+ updateDirtyFieldsBaseOnDefaultValues(defaultFieldArrayValues, updatedFieldArrayValues);
1478
+ updateDirtyFieldsBaseOnDefaultValues(updatedFieldArrayValues, defaultFieldArrayValues);
1437
1479
  }
1438
1480
  };
1439
- const cleanup = (ref) => !filterOutFalsy(get(ref, name, [])).length && unset(ref, name);
1440
- const batchStateUpdate = (method, args, isDirty = true, shouldSet = true, shouldUpdateValid = false) => {
1481
+ const batchStateUpdate = (method, args, updatedFieldValues, isDirty = true, shouldSet = true, shouldUpdateValid = false) => {
1441
1482
  if (get(shallowFieldsStateRef.current, name)) {
1442
1483
  const output = method(get(shallowFieldsStateRef.current, name), args.argA, args.argB);
1443
1484
  shouldSet && set(shallowFieldsStateRef.current, name, output);
@@ -1447,21 +1488,23 @@ const useFieldArray = ({ control, name, keyName = 'id', }) => {
1447
1488
  shouldSet && set(fieldArrayDefaultValuesRef.current, name, output);
1448
1489
  cleanup(fieldArrayDefaultValuesRef.current);
1449
1490
  }
1450
- if (isArray(get(formStateRef.current.errors, name))) {
1491
+ if (Array.isArray(get(formStateRef.current.errors, name))) {
1451
1492
  const output = method(get(formStateRef.current.errors, name), args.argA, args.argB);
1452
1493
  shouldSet && set(formStateRef.current.errors, name, output);
1453
1494
  cleanup(formStateRef.current.errors);
1454
1495
  }
1455
- if (readFormStateRef.current.touched && get(touched, name)) {
1456
- const output = method(get(touched, name), args.argA, args.argB);
1457
- shouldSet && set(touched, name, output);
1458
- cleanup(touched);
1496
+ if (readFormStateRef.current.touched &&
1497
+ get(formStateRef.current.touched, name)) {
1498
+ const output = method(get(formStateRef.current.touched, name), args.argA, args.argB);
1499
+ shouldSet && set(formStateRef.current.touched, name, output);
1500
+ cleanup(formStateRef.current.touched);
1459
1501
  }
1460
1502
  if (readFormStateRef.current.dirtyFields ||
1461
1503
  readFormStateRef.current.isDirty) {
1462
- const output = method(get(dirtyFields, name, []), args.argC, args.argD);
1463
- shouldSet && set(dirtyFields, name, output);
1464
- cleanup(dirtyFields);
1504
+ const output = method(get(formStateRef.current.dirtyFields, name, []), args.argC, args.argD);
1505
+ shouldSet && set(formStateRef.current.dirtyFields, name, output);
1506
+ updateDirtyFieldsWithDefaultValues(updatedFieldValues);
1507
+ cleanup(formStateRef.current.dirtyFields);
1465
1508
  }
1466
1509
  if (shouldUpdateValid &&
1467
1510
  readFormStateRef.current.isValid &&
@@ -1473,30 +1516,23 @@ const useFieldArray = ({ control, name, keyName = 'id', }) => {
1473
1516
  }
1474
1517
  updateFormState({
1475
1518
  errors: formStateRef.current.errors,
1476
- dirtyFields,
1519
+ dirtyFields: formStateRef.current.dirtyFields,
1477
1520
  isDirty,
1478
- touched,
1521
+ touched: formStateRef.current.touched,
1479
1522
  });
1480
1523
  };
1481
1524
  const append = (value, shouldFocus = true) => {
1482
- setFieldAndValidState([
1525
+ const updateFormValues = [
1483
1526
  ...allFields.current,
1484
- ...(isArray(value)
1485
- ? appendValueWithKey(value)
1486
- : [appendId(value, keyName)]),
1487
- ]);
1527
+ ...mapIds(Array.isArray(value) ? value : [value], keyName),
1528
+ ];
1529
+ setFieldAndValidState(updateFormValues);
1488
1530
  if (readFormStateRef.current.dirtyFields ||
1489
1531
  readFormStateRef.current.isDirty) {
1490
- const dirtyInputs = get(dirtyFields, name, []);
1491
- set(dirtyFields, name, [
1492
- ...(allFields.current.length > dirtyInputs.length
1493
- ? (fillEmptyArray(allFields.current) || []).map((_, index) => dirtyInputs[index])
1494
- : dirtyInputs),
1495
- ...filterBooleanArray(value),
1496
- ]);
1532
+ updateDirtyFieldsWithDefaultValues(updateFormValues);
1497
1533
  updateFormState({
1498
1534
  isDirty: true,
1499
- dirtyFields,
1535
+ dirtyFields: formStateRef.current.dirtyFields,
1500
1536
  });
1501
1537
  }
1502
1538
  if (!shouldUnregister) {
@@ -1509,34 +1545,37 @@ const useFieldArray = ({ control, name, keyName = 'id', }) => {
1509
1545
  };
1510
1546
  const prepend$1 = (value, shouldFocus = true) => {
1511
1547
  const emptyArray = fillEmptyArray(value);
1512
- setFieldAndValidState(prepend(getCurrentFieldsValues(), isArray(value) ? appendValueWithKey(value) : [appendId(value, keyName)]));
1548
+ const updatedFieldArrayValues = prepend(getCurrentFieldsValues(), mapIds(Array.isArray(value) ? value : [value], keyName));
1549
+ setFieldAndValidState(updatedFieldArrayValues);
1513
1550
  resetFields();
1514
1551
  batchStateUpdate(prepend, {
1515
1552
  argA: emptyArray,
1516
- argC: filterBooleanArray(value),
1517
- });
1553
+ argC: fillBooleanArray(value),
1554
+ }, updatedFieldArrayValues);
1518
1555
  focusIndexRef.current = shouldFocus ? 0 : -1;
1519
1556
  };
1520
1557
  const remove = (index) => {
1521
1558
  const fieldValues = getCurrentFieldsValues();
1522
- setFieldAndValidState(removeArrayAt(fieldValues, index));
1559
+ const updatedFieldValues = removeArrayAt(fieldValues, index);
1560
+ setFieldAndValidState(updatedFieldValues);
1523
1561
  resetFields();
1524
1562
  batchStateUpdate(removeArrayAt, {
1525
1563
  argA: index,
1526
1564
  argC: index,
1527
- }, getIsDirtyState(removeArrayAt(fieldValues, index)), true, true);
1565
+ }, updatedFieldValues, getIsDirtyState(removeArrayAt(fieldValues, index)), true, true);
1528
1566
  };
1529
1567
  const insert$1 = (index, value, shouldFocus = true) => {
1530
1568
  const emptyArray = fillEmptyArray(value);
1531
1569
  const fieldValues = getCurrentFieldsValues();
1532
- setFieldAndValidState(insert(fieldValues, index, isArray(value) ? appendValueWithKey(value) : [appendId(value, keyName)]));
1570
+ const updatedFieldArrayValues = insert(fieldValues, index, mapIds(Array.isArray(value) ? value : [value], keyName));
1571
+ setFieldAndValidState(updatedFieldArrayValues);
1533
1572
  resetFields();
1534
1573
  batchStateUpdate(insert, {
1535
1574
  argA: index,
1536
1575
  argB: emptyArray,
1537
1576
  argC: index,
1538
- argD: filterBooleanArray(value),
1539
- }, getIsDirtyState(insert(fieldValues, index)));
1577
+ argD: fillBooleanArray(value),
1578
+ }, updatedFieldArrayValues, getIsDirtyState(insert(fieldValues, index)));
1540
1579
  focusIndexRef.current = shouldFocus ? index : -1;
1541
1580
  };
1542
1581
  const swap = (indexA, indexB) => {
@@ -1549,7 +1588,7 @@ const useFieldArray = ({ control, name, keyName = 'id', }) => {
1549
1588
  argB: indexB,
1550
1589
  argC: indexA,
1551
1590
  argD: indexB,
1552
- }, getIsDirtyState(fieldValues), false);
1591
+ }, undefined, getIsDirtyState(fieldValues), false);
1553
1592
  };
1554
1593
  const move = (from, to) => {
1555
1594
  const fieldValues = getCurrentFieldsValues();
@@ -1561,7 +1600,7 @@ const useFieldArray = ({ control, name, keyName = 'id', }) => {
1561
1600
  argB: to,
1562
1601
  argC: from,
1563
1602
  argD: to,
1564
- }, getIsDirtyState(fieldValues), false);
1603
+ }, undefined, getIsDirtyState(fieldValues), false);
1565
1604
  };
1566
1605
  const reset = (data) => {
1567
1606
  resetFields();
@@ -1581,20 +1620,7 @@ const useFieldArray = ({ control, name, keyName = 'id', }) => {
1581
1620
  defaultValues.pop();
1582
1621
  set(fieldArrayDefaultValuesRef.current, name, defaultValues);
1583
1622
  }
1584
- if (isWatchAllRef.current) {
1585
- updateFormState();
1586
- }
1587
- else if (watchFieldsRef) {
1588
- let shouldRenderUseWatch = true;
1589
- for (const watchField of watchFieldsRef.current) {
1590
- if (watchField.startsWith(name)) {
1591
- updateFormState();
1592
- shouldRenderUseWatch = false;
1593
- break;
1594
- }
1595
- }
1596
- shouldRenderUseWatch && renderWatchedInputs(name);
1597
- }
1623
+ updateWatchedValue(name);
1598
1624
  if (focusIndexRef.current > -1) {
1599
1625
  for (const key in fieldsRef.current) {
1600
1626
  const field = fieldsRef.current[key];
@@ -1641,7 +1667,7 @@ function useWatch({ control, name, defaultValue, }) {
1641
1667
  const [value, setValue] = React.useState(isUndefined(defaultValue)
1642
1668
  ? isString(name)
1643
1669
  ? get(defaultValuesRef.current, name)
1644
- : isArray(name)
1670
+ : Array.isArray(name)
1645
1671
  ? name.reduce((previous, inputName) => (Object.assign(Object.assign({}, previous), { [inputName]: get(defaultValuesRef.current, inputName) })), {})
1646
1672
  : defaultValuesRef.current
1647
1673
  : defaultValue);
@@ -1649,7 +1675,10 @@ function useWatch({ control, name, defaultValue, }) {
1649
1675
  const defaultValueRef = React.useRef(defaultValue);
1650
1676
  const updateWatchValue = React.useCallback(() => {
1651
1677
  const value = watchInternal(name, defaultValueRef.current, idRef.current);
1652
- setValue(isObject(value) ? Object.assign({}, value) : isArray(value) ? [...value] : value);
1678
+ setValue(isObject(value)
1679
+ ? Object.assign({}, value) : Array.isArray(value)
1680
+ ? [...value]
1681
+ : value);
1653
1682
  }, [setValue, watchInternal, defaultValueRef, name, idRef]);
1654
1683
  React.useEffect(() => {
1655
1684
  {
@@ -1736,9 +1765,7 @@ const Controller = (_a) => {
1736
1765
  }
1737
1766
  }
1738
1767
  }, [rules, name, register]);
1739
- React.useEffect(() => () => {
1740
- !isNameInFieldArray(fieldArrayNamesRef.current, name) && unregister(name);
1741
- }, [unregister, name, fieldArrayNamesRef]);
1768
+ React.useEffect(() => () => unregister(name), [unregister, name]);
1742
1769
  React.useEffect(() => {
1743
1770
  {
1744
1771
  if (isUndefined(value)) {