react-hook-form 7.78.0 → 7.80.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"createFormControl.d.ts","sourceRoot":"","sources":["../../src/logic/createFormControl.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAcV,WAAW,EAiBX,YAAY,EAKZ,aAAa,EAYd,MAAM,UAAU,CAAC;AAuDlB,eAAO,MAAM,kBAAkB;;;;;;;;;;;;CAY9B,CAAC;AAEF,wBAAgB,iBAAiB,CAC/B,YAAY,SAAS,WAAW,GAAG,WAAW,EAC9C,QAAQ,GAAG,GAAG,EACd,kBAAkB,GAAG,YAAY,EAEjC,KAAK,GAAE,YAAY,CAAC,YAAY,EAAE,QAAQ,EAAE,kBAAkB,CAAM,GACnE,IAAI,CACL,aAAa,CAAC,YAAY,EAAE,QAAQ,EAAE,kBAAkB,CAAC,EACzD,WAAW,CACZ,GAAG;IACF,WAAW,EAAE,IAAI,CACf,aAAa,CAAC,YAAY,EAAE,QAAQ,EAAE,kBAAkB,CAAC,EACzD,WAAW,CACZ,CAAC;CACH,CAyvDA"}
1
+ {"version":3,"file":"createFormControl.d.ts","sourceRoot":"","sources":["../../src/logic/createFormControl.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAcV,WAAW,EAiBX,YAAY,EAKZ,aAAa,EAYd,MAAM,UAAU,CAAC;AAyDlB,eAAO,MAAM,kBAAkB;;;;;;;;;;;;CAY9B,CAAC;AAEF,wBAAgB,iBAAiB,CAC/B,YAAY,SAAS,WAAW,GAAG,WAAW,EAC9C,QAAQ,GAAG,GAAG,EACd,kBAAkB,GAAG,YAAY,EAEjC,KAAK,GAAE,YAAY,CAAC,YAAY,EAAE,QAAQ,EAAE,kBAAkB,CAAM,GACnE,IAAI,CACL,aAAa,CAAC,YAAY,EAAE,QAAQ,EAAE,kBAAkB,CAAC,EACzD,WAAW,CACZ,GAAG;IACF,WAAW,EAAE,IAAI,CACf,aAAa,CAAC,YAAY,EAAE,QAAQ,EAAE,kBAAkB,CAAC,EACzD,WAAW,CACZ,CAAC;CACH,CA0yDA"}
@@ -1 +1 @@
1
- {"version":3,"file":"getNodeParentName.d.ts","sourceRoot":"","sources":["../../src/logic/getNodeParentName.ts"],"names":[],"mappings":"yBAAgB,MAAM,MAAM;AAA5B,wBACwD"}
1
+ {"version":3,"file":"getNodeParentName.d.ts","sourceRoot":"","sources":["../../src/logic/getNodeParentName.ts"],"names":[],"mappings":"yBAEgB,MAAM,MAAM;AAA5B,wBACyD"}
@@ -1 +1 @@
1
- {"version":3,"file":"hasPromiseValidation.d.ts","sourceRoot":"","sources":["../../src/logic/hasPromiseValidation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAY,MAAM,UAAU,CAAC;yBAMhC,gBAAgB,KAAK,CAAC,IAAI,CAAC;AAA3C,wBAWI"}
1
+ {"version":3,"file":"hasPromiseValidation.d.ts","sourceRoot":"","sources":["../../src/logic/hasPromiseValidation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAY,MAAM,UAAU,CAAC;yBAMhC,gBAAgB,KAAK,CAAC,IAAI,CAAC;AAA3C,wBAmBE"}
@@ -1 +1 @@
1
- {"version":3,"file":"isWatched.d.ts","sourceRoot":"","sources":["../../src/logic/isWatched.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;yBAGvD,MAAM,iBAAiB,EACvB,QAAQ,KAAK,EACb,cAAc,OAAO;AAHvB,wBAQ6E"}
1
+ {"version":3,"file":"isWatched.d.ts","sourceRoot":"","sources":["../../src/logic/isWatched.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;yBAGvD,MAAM,iBAAiB,EACvB,QAAQ,KAAK,EACb,cAAc,OAAO;AAHvB,wBAYE"}
@@ -1 +1 @@
1
- {"version":3,"file":"shouldRenderFormState.d.ts","sourceRoot":"","sources":["../../src/logic/shouldRenderFormState.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,WAAW,EACX,SAAS,EACT,iBAAiB,EACjB,aAAa,EACd,MAAM,UAAU,CAAC;yBAGF,CAAC,SAAS,WAAW,EAAE,CAAC,SAAS,aAAa,EAC5D,eAAe,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG;IACrC,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB,MAAM,CAAC,EAAE,CAAC,CAAC;CACZ,EACD,iBAAiB,CAAC,EAClB,iBAAiB,CAAC,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,EAC3D,SAAS,OAAO;AAPlB,wBAsBE"}
1
+ {"version":3,"file":"shouldRenderFormState.d.ts","sourceRoot":"","sources":["../../src/logic/shouldRenderFormState.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,WAAW,EACX,SAAS,EACT,iBAAiB,EACjB,aAAa,EACd,MAAM,UAAU,CAAC;yBAEF,CAAC,SAAS,WAAW,EAAE,CAAC,SAAS,aAAa,EAC5D,eAAe,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG;IACrC,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB,MAAM,CAAC,EAAE,CAAC,CAAC;CACZ,EACD,iBAAiB,CAAC,EAClB,iBAAiB,CAAC,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,EAC3D,SAAS,OAAO;AAPlB,wBAsBE"}
@@ -1 +1 @@
1
- {"version":3,"file":"validateField.d.ts","sourceRoot":"","sources":["../../src/logic/validateField.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,KAAK,EAEL,WAAW,EACX,mBAAmB,EACnB,eAAe,EAKhB,MAAM,UAAU,CAAC;yBAqBI,CAAC,SAAS,WAAW,EACzC,OAAO,KAAK,EACZ,oBAAoB,eAAe,EACnC,YAAY,CAAC,EACb,0BAA0B,OAAO,EACjC,4BAA4B,OAAO,EACnC,eAAe,OAAO,KACrB,OAAO,CAAC,mBAAmB,CAAC;AAP/B,wBA6PE"}
1
+ {"version":3,"file":"validateField.d.ts","sourceRoot":"","sources":["../../src/logic/validateField.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,KAAK,EAEL,WAAW,EACX,mBAAmB,EACnB,eAAe,EAKhB,MAAM,UAAU,CAAC;yBAqBI,CAAC,SAAS,WAAW,EACzC,OAAO,KAAK,EACZ,oBAAoB,eAAe,EACnC,YAAY,CAAC,EACb,0BAA0B,OAAO,EACjC,4BAA4B,OAAO,EACnC,eAAe,OAAO,KACrB,OAAO,CAAC,mBAAmB,CAAC;AAP/B,wBAkQE"}
@@ -31,7 +31,6 @@ const INPUT_VALIDATION_RULES = {
31
31
  required: 'required',
32
32
  validate: 'validate',
33
33
  };
34
- const FORM_ERROR_TYPE = 'form';
35
34
  const ROOT_ERROR_TYPE = 'root';
36
35
  const PROTOTYPE_KEYWORDS = ['__proto__', 'constructor', 'prototype'];
37
36
 
@@ -110,7 +109,7 @@ var createSubject = () => {
110
109
  var isPrimitive = (value) => isNullOrUndefined(value) || !isObjectType(value);
111
110
 
112
111
  const isEmptyObjectWithCustomPrototype = (object, keys) => keys.length === 0 && !Array.isArray(object) && !isPlainObject(object);
113
- function deepEqual(object1, object2, visited = new WeakSet()) {
112
+ function deepEqual(object1, object2, visited = new WeakMap()) {
114
113
  if (object1 === object2) {
115
114
  return true;
116
115
  }
@@ -129,11 +128,21 @@ function deepEqual(object1, object2, visited = new WeakSet()) {
129
128
  isEmptyObjectWithCustomPrototype(object2, keys2)) {
130
129
  return Object.is(object1, object2);
131
130
  }
132
- if (visited.has(object1) || visited.has(object2)) {
131
+ if (!keys1.length && Array.isArray(object1) !== Array.isArray(object2)) {
132
+ return false;
133
+ }
134
+ const visitedPairs = visited.get(object1);
135
+ if (visitedPairs && visitedPairs.has(object2)) {
133
136
  return true;
134
137
  }
135
- visited.add(object1);
136
- visited.add(object2);
138
+ if (visitedPairs) {
139
+ visitedPairs.add(object2);
140
+ }
141
+ else {
142
+ const ws = new WeakSet();
143
+ ws.add(object2);
144
+ visited.set(object1, ws);
145
+ }
137
146
  for (const key of keys1) {
138
147
  const val1 = object1[key];
139
148
  if (!(key in object2)) {
@@ -173,11 +182,13 @@ function extractFormValues(fieldsState, formValues) {
173
182
  return values;
174
183
  }
175
184
 
176
- var isKey = (value) => /^\w*$/.test(value);
185
+ const IS_KEY_RE = /^\w*$/;
186
+ var isKey = (value) => IS_KEY_RE.test(value);
177
187
 
178
188
  var isUndefined = (val) => val === undefined;
179
189
 
180
- var stringToPath = (input) => input.split(/[.[\]'"]/g).filter(Boolean);
190
+ const FIELD_PATH_RE = /[.[\]'"]/;
191
+ var stringToPath = (input) => input.split(FIELD_PATH_RE).filter(Boolean);
181
192
 
182
193
  var get = (object, path, defaultValue) => {
183
194
  if (!path || !isObject(object)) {
@@ -489,12 +500,22 @@ var getValidationModes = (mode) => ({
489
500
  });
490
501
 
491
502
  const ASYNC_FUNCTION = 'AsyncFunction';
492
- var hasPromiseValidation = (fieldReference) => !!fieldReference &&
493
- !!fieldReference.validate &&
494
- !!((isFunction(fieldReference.validate) &&
495
- fieldReference.validate.constructor.name === ASYNC_FUNCTION) ||
496
- (isObject(fieldReference.validate) &&
497
- Object.values(fieldReference.validate).find((validateFunction) => validateFunction.constructor.name === ASYNC_FUNCTION)));
503
+ var hasPromiseValidation = (fieldReference) => {
504
+ if (!fieldReference || !fieldReference.validate)
505
+ return false;
506
+ if (isFunction(fieldReference.validate)) {
507
+ return fieldReference.validate.constructor.name === ASYNC_FUNCTION;
508
+ }
509
+ if (isObject(fieldReference.validate)) {
510
+ for (const key in fieldReference.validate) {
511
+ if (fieldReference.validate[key].constructor
512
+ .name === ASYNC_FUNCTION) {
513
+ return true;
514
+ }
515
+ }
516
+ }
517
+ return false;
518
+ };
498
519
 
499
520
  var hasValidation = (options) => options.mount &&
500
521
  (options.required ||
@@ -509,10 +530,17 @@ var isNameInFieldArray = (names, name) => name
509
530
  .split('.')
510
531
  .some((part, index, arr) => !isNaN(Number(part)) && names.has(arr.slice(0, index).join('.')));
511
532
 
512
- var isWatched = (name, _names, isBlurEvent) => !isBlurEvent &&
513
- (_names.watchAll ||
514
- _names.watch.has(name) ||
515
- [..._names.watch].some((watchName) => name.startsWith(`${watchName}.`)));
533
+ var isWatched = (name, _names, isBlurEvent) => {
534
+ if (isBlurEvent)
535
+ return false;
536
+ if (_names.watchAll || _names.watch.has(name))
537
+ return true;
538
+ for (const watchName of _names.watch) {
539
+ if (name.startsWith(watchName) && name.charAt(watchName.length) === '.')
540
+ return true;
541
+ }
542
+ return false;
543
+ };
516
544
 
517
545
  const iterateFieldsByAction = (fields, action, fieldsNames, abortEarly) => {
518
546
  for (const key of fieldsNames || Object.keys(fields)) {
@@ -580,10 +608,10 @@ function schemaErrorLookup(errors, _fields, name) {
580
608
  var shouldRenderFormState = (formStateData, _proxyFormState, updateFormState, isRoot) => {
581
609
  updateFormState(formStateData);
582
610
  const { name, ...formState } = formStateData;
583
- return (isEmptyObject(formState) ||
584
- (isRoot &&
585
- Object.keys(formState).length >= Object.keys(_proxyFormState).length) ||
586
- Object.keys(formState).find((key) => _proxyFormState[key] ===
611
+ const keys = Object.keys(formState);
612
+ return (!keys.length ||
613
+ (isRoot && keys.length >= Object.keys(_proxyFormState).length) ||
614
+ keys.find((key) => _proxyFormState[key] ===
587
615
  (!isRoot || VALIDATION_MODE.all)));
588
616
  };
589
617
 
@@ -650,7 +678,13 @@ var validateField = async (field, disabledFieldNames, formValues, validateAllFie
650
678
  const inputRef = refs ? refs[0] : ref;
651
679
  const setCustomValidity = (message) => {
652
680
  if (shouldUseNativeValidation && inputRef.reportValidity) {
653
- inputRef.setCustomValidity(isBoolean(message) ? '' : message || '');
681
+ const validityMessage = isBoolean(message) ? '' : message || '';
682
+ if (refs) {
683
+ refs.forEach((ref) => ref.setCustomValidity(validityMessage));
684
+ }
685
+ else {
686
+ inputRef.setCustomValidity(validityMessage);
687
+ }
654
688
  inputRef.reportValidity();
655
689
  }
656
690
  };
@@ -825,6 +859,7 @@ const defaultOptions = {
825
859
  reValidateMode: VALIDATION_MODE.onChange,
826
860
  shouldFocusError: true,
827
861
  };
862
+ const FORM_ERROR_TYPE = 'form';
828
863
  const DEFAULT_FORM_STATE = {
829
864
  submitCount: 0,
830
865
  isDirty: false,
@@ -872,6 +907,9 @@ function createFormControl(props = {}) {
872
907
  };
873
908
  let delayErrorCallback;
874
909
  let timer = 0;
910
+ let _valuesSubscriberCount = 0;
911
+ let _validationModeBeforeSubmit = getValidationModes(_options.mode);
912
+ let _validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
875
913
  const defaultProxyFormState = {
876
914
  isDirty: false,
877
915
  dirtyFields: false,
@@ -982,6 +1020,7 @@ function createFormControl(props = {}) {
982
1020
  };
983
1021
  const updateErrors = (name, error) => {
984
1022
  set(_formState.errors, name, error);
1023
+ _formState.errors = { ..._formState.errors };
985
1024
  _subjects.state.next({
986
1025
  errors: _formState.errors,
987
1026
  });
@@ -1024,12 +1063,6 @@ function createFormControl(props = {}) {
1024
1063
  : setFieldValue(name, defaultValue);
1025
1064
  if (_state.mount && !_state.action) {
1026
1065
  _setValid();
1027
- // Re-registering a field after a prior unregister puts its key back
1028
- // into _formValues, which can flip isDirty back to false (#13397).
1029
- // Only run when we are currently dirty, otherwise an initial register
1030
- // for a field with no defaultValue would flip isDirty to true. Reset
1031
- // paths repopulate _formValues before re-register, so the key is
1032
- // present then and this branch is skipped (preserves keepDirty).
1033
1066
  if (wasUnsetInFormValues &&
1034
1067
  _formState.isDirty &&
1035
1068
  (_proxyFormState.isDirty || _proxySubscribeFormState.isDirty)) {
@@ -1039,6 +1072,12 @@ function createFormControl(props = {}) {
1039
1072
  _subjects.state.next({ ..._formState });
1040
1073
  }
1041
1074
  }
1075
+ if (props.shouldUnregister &&
1076
+ wasUnsetInFormValues &&
1077
+ !isUndefined(get(_formValues, name)) &&
1078
+ isWatched(name, _names)) {
1079
+ _state.watch = true;
1080
+ }
1042
1081
  }
1043
1082
  }
1044
1083
  };
@@ -1050,12 +1089,13 @@ function createFormControl(props = {}) {
1050
1089
  };
1051
1090
  if (!_options.disabled) {
1052
1091
  if (!isBlurEvent || shouldDirty) {
1092
+ const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
1053
1093
  if (_proxyFormState.isDirty || _proxySubscribeFormState.isDirty) {
1054
1094
  isPreviousDirty = _formState.isDirty;
1055
- _formState.isDirty = output.isDirty = _getDirty();
1095
+ _formState.isDirty = output.isDirty =
1096
+ !isCurrentFieldPristine || _getDirty();
1056
1097
  shouldUpdateField = isPreviousDirty !== output.isDirty;
1057
1098
  }
1058
- const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
1059
1099
  isPreviousDirty = !!get(_formState.dirtyFields, name);
1060
1100
  if (isCurrentFieldPristine !== _formState.isDirty) {
1061
1101
  _formState.dirtyFields = getDirtyFields(_defaultValues, _formValues);
@@ -1103,6 +1143,7 @@ function createFormControl(props = {}) {
1103
1143
  error
1104
1144
  ? set(_formState.errors, name, error)
1105
1145
  : unset(_formState.errors, name);
1146
+ _formState.errors = { ..._formState.errors };
1106
1147
  }
1107
1148
  if ((error ? !deepEqual(previousFieldError, error) : previousFieldError) ||
1108
1149
  !isEmptyObject(fieldState) ||
@@ -1138,6 +1179,7 @@ function createFormControl(props = {}) {
1138
1179
  : set(_formState.errors, name, error)
1139
1180
  : unset(_formState.errors, name);
1140
1181
  }
1182
+ _formState.errors = { ..._formState.errors };
1141
1183
  }
1142
1184
  else {
1143
1185
  _formState.errors = errors;
@@ -1252,7 +1294,7 @@ function createFormControl(props = {}) {
1252
1294
  };
1253
1295
  const _getDirty = (name, data) => !_options.disabled &&
1254
1296
  (name && data && set(_formValues, name, data),
1255
- !deepEqual(getValues(), _defaultValues));
1297
+ !deepEqual(_state.mount ? _formValues : _defaultValues, _defaultValues));
1256
1298
  const _getWatch = (names, defaultValue, isGlobal) => generateWatchOutput(names, _names, {
1257
1299
  ...(_state.mount
1258
1300
  ? _formValues
@@ -1263,7 +1305,7 @@ function createFormControl(props = {}) {
1263
1305
  : defaultValue),
1264
1306
  }, isGlobal, defaultValue);
1265
1307
  const _getFieldArray = (name) => compact(get(_state.mount ? _formValues : _defaultValues, name, _options.shouldUnregister ? get(_defaultValues, name, []) : []));
1266
- const setFieldValue = (name, value, options = {}, skipClone = false) => {
1308
+ const setFieldValue = (name, value, options = {}, skipClone = false, skipRender = false) => {
1267
1309
  const field = get(_fields, name);
1268
1310
  let fieldValue = value;
1269
1311
  if (field) {
@@ -1301,7 +1343,7 @@ function createFormControl(props = {}) {
1301
1343
  }
1302
1344
  else {
1303
1345
  fieldReference.ref.value = fieldValue;
1304
- if (!fieldReference.ref.type) {
1346
+ if (!fieldReference.ref.type && !skipRender) {
1305
1347
  _subjects.state.next({
1306
1348
  name,
1307
1349
  values: skipClone ? _formValues : cloneObject(_formValues),
@@ -1311,10 +1353,10 @@ function createFormControl(props = {}) {
1311
1353
  }
1312
1354
  }
1313
1355
  (options.shouldDirty || options.shouldTouch) &&
1314
- updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty, true);
1356
+ updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty, !skipRender);
1315
1357
  options.shouldValidate && trigger(name);
1316
1358
  };
1317
- const setFieldValues = (name, value, options, skipClone = false) => {
1359
+ const setFieldValues = (name, value, options, skipClone = false, skipRender = false) => {
1318
1360
  for (const fieldKey in value) {
1319
1361
  if (!value.hasOwnProperty(fieldKey)) {
1320
1362
  return;
@@ -1326,11 +1368,11 @@ function createFormControl(props = {}) {
1326
1368
  isObject(fieldValue) ||
1327
1369
  (field && !field._f)) &&
1328
1370
  !isDateObject(fieldValue)
1329
- ? setFieldValues(fieldName, fieldValue, options, skipClone)
1330
- : setFieldValue(fieldName, fieldValue, options, skipClone);
1371
+ ? setFieldValues(fieldName, fieldValue, options, skipClone, skipRender)
1372
+ : setFieldValue(fieldName, fieldValue, options, skipClone, skipRender);
1331
1373
  }
1332
1374
  };
1333
- const _setValue = (name, value, options, skipClone) => {
1375
+ const _setValue = (name, value, options, skipClone, skipStateEmit = false) => {
1334
1376
  const field = get(_fields, name);
1335
1377
  const isFieldArray = _names.array.has(name);
1336
1378
  const cloneValue = skipClone ? value : cloneObject(value);
@@ -1350,24 +1392,26 @@ function createFormControl(props = {}) {
1350
1392
  _proxySubscribeFormState.dirtyFields) &&
1351
1393
  options.shouldDirty) {
1352
1394
  _updateDirtyFields();
1353
- _subjects.state.next({
1354
- name,
1355
- dirtyFields: _formState.dirtyFields,
1356
- isDirty: _getDirty(name, cloneValue),
1357
- });
1395
+ if (!skipStateEmit) {
1396
+ _subjects.state.next({
1397
+ name,
1398
+ dirtyFields: _formState.dirtyFields,
1399
+ isDirty: _getDirty(name, cloneValue),
1400
+ });
1401
+ }
1358
1402
  }
1359
1403
  }
1360
1404
  else {
1361
1405
  const isEmpty = (Array.isArray(cloneValue) && !cloneValue.length) ||
1362
1406
  isEmptyObject(cloneValue);
1363
1407
  if (!field || field._f || isNullOrUndefined(cloneValue) || isEmpty) {
1364
- setFieldValue(name, cloneValue, options, skipClone);
1408
+ setFieldValue(name, cloneValue, options, skipClone, skipStateEmit);
1365
1409
  }
1366
1410
  else {
1367
- setFieldValues(name, cloneValue, options, skipClone);
1411
+ setFieldValues(name, cloneValue, options, skipClone, skipStateEmit);
1368
1412
  }
1369
1413
  }
1370
- if (!isValueUnchanged) {
1414
+ if (!isValueUnchanged && !skipStateEmit) {
1371
1415
  const watched = isWatched(name, _names);
1372
1416
  const values = skipClone ? _formValues : cloneObject(_formValues);
1373
1417
  _subjects.state.next({
@@ -1388,13 +1432,13 @@ function createFormControl(props = {}) {
1388
1432
  ...updatedFormValues,
1389
1433
  };
1390
1434
  for (const fieldName of _names.mount) {
1391
- _setValue(fieldName, get(updatedFormValues, fieldName), options, true);
1435
+ _setValue(fieldName, get(updatedFormValues, fieldName), options, true, true);
1392
1436
  }
1393
1437
  _subjects.state.next({
1394
1438
  ..._formState,
1395
1439
  name: undefined,
1396
1440
  type: undefined,
1397
- values: _formValues,
1441
+ ...(_valuesSubscriberCount ? { values: _formValues } : {}),
1398
1442
  });
1399
1443
  if (options.shouldValidate) {
1400
1444
  _setValid();
@@ -1413,8 +1457,6 @@ function createFormControl(props = {}) {
1413
1457
  (isDateObject(fieldValue) && isNaN(fieldValue.getTime())) ||
1414
1458
  deepEqual(fieldValue, get(_formValues, name, fieldValue));
1415
1459
  };
1416
- const validationModeBeforeSubmit = getValidationModes(_options.mode);
1417
- const validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
1418
1460
  if (field) {
1419
1461
  let error;
1420
1462
  let isValid;
@@ -1422,12 +1464,13 @@ function createFormControl(props = {}) {
1422
1464
  ? getFieldValue(field._f)
1423
1465
  : getEventValue(event);
1424
1466
  const isBlurEvent = event.type === EVENTS.BLUR || event.type === EVENTS.FOCUS_OUT;
1425
- const shouldSkipValidation = (!hasValidation(field._f) &&
1467
+ const hasNoValidationEffect = !hasValidation(field._f) &&
1426
1468
  !props.validate &&
1427
1469
  !_options.resolver &&
1428
1470
  !get(_formState.errors, name) &&
1429
- !field._f.deps) ||
1430
- skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, validationModeAfterSubmit, validationModeBeforeSubmit);
1471
+ !field._f.deps;
1472
+ const shouldSkipValidation = hasNoValidationEffect ||
1473
+ skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, _validationModeAfterSubmit, _validationModeBeforeSubmit);
1431
1474
  const watched = isWatched(name, _names, isBlurEvent);
1432
1475
  set(_formValues, name, fieldValue);
1433
1476
  if (isBlurEvent) {
@@ -1445,10 +1488,13 @@ function createFormControl(props = {}) {
1445
1488
  _subjects.state.next({
1446
1489
  name,
1447
1490
  type: event.type,
1448
- values: cloneObject(_formValues),
1491
+ ...(_valuesSubscriberCount
1492
+ ? { values: cloneObject(_formValues) }
1493
+ : {}),
1449
1494
  });
1450
1495
  if (shouldSkipValidation) {
1451
- if (_proxyFormState.isValid || _proxySubscribeFormState.isValid) {
1496
+ if ((!hasNoValidationEffect || !_formState.isValid) &&
1497
+ (_proxyFormState.isValid || _proxySubscribeFormState.isValid)) {
1452
1498
  if (_options.mode === 'onBlur') {
1453
1499
  if (isBlurEvent) {
1454
1500
  _setValid();
@@ -1583,8 +1629,6 @@ function createFormControl(props = {}) {
1583
1629
  const names = name ? convertToArrayPayload(name) : undefined;
1584
1630
  names === null || names === void 0 ? void 0 : names.forEach((inputName) => unset(_formState.errors, inputName));
1585
1631
  if (names) {
1586
- // Emit for each cleared field with the field name so that
1587
- // shouldSubscribeByName can filter and avoid broad re-renders
1588
1632
  names.forEach((inputName) => {
1589
1633
  _subjects.state.next({
1590
1634
  name: inputName,
@@ -1593,7 +1637,6 @@ function createFormControl(props = {}) {
1593
1637
  });
1594
1638
  }
1595
1639
  else {
1596
- // Clear all errors - emit without name to notify all subscribers
1597
1640
  _subjects.state.next({
1598
1641
  errors: {},
1599
1642
  });
@@ -1602,7 +1645,6 @@ function createFormControl(props = {}) {
1602
1645
  const setError = (name, error, options) => {
1603
1646
  const ref = (get(_fields, name, { _f: {} })._f || {}).ref;
1604
1647
  const currentError = get(_formState.errors, name) || {};
1605
- // Don't override existing error messages elsewhere in the object tree.
1606
1648
  const { ref: currentRef, message, type, ...restOfErrorTree } = currentError;
1607
1649
  set(_formState.errors, name, {
1608
1650
  ...restOfErrorTree,
@@ -1616,26 +1658,60 @@ function createFormControl(props = {}) {
1616
1658
  });
1617
1659
  options && options.shouldFocus && ref && ref.focus && ref.focus();
1618
1660
  };
1619
- const watch = (name, defaultValue) => isFunction(name)
1620
- ? _subjects.state.subscribe({
1621
- next: (payload) => 'values' in payload &&
1622
- name(payload.values || _getWatch(undefined, defaultValue), payload),
1623
- })
1624
- : _getWatch(name, defaultValue, true);
1625
- const _subscribe = (props) => _subjects.state.subscribe({
1626
- next: (formState) => {
1627
- if (shouldSubscribeByName(props.name, formState.name, props.exact) &&
1628
- shouldRenderFormState(formState, props.formState || _proxyFormState, _setFormState, props.reRenderRoot)) {
1629
- const snapshot = { ..._formValues };
1630
- props.callback({
1631
- values: snapshot,
1632
- ..._formState,
1633
- ...formState,
1634
- defaultValues: _defaultValues,
1635
- });
1661
+ const watch = (name, defaultValue) => {
1662
+ if (isFunction(name)) {
1663
+ _valuesSubscriberCount++;
1664
+ const { unsubscribe } = _subjects.state.subscribe({
1665
+ next: (payload) => 'values' in payload &&
1666
+ name(payload.values || _getWatch(undefined, defaultValue), payload),
1667
+ });
1668
+ let called = false;
1669
+ return {
1670
+ unsubscribe: () => {
1671
+ if (called) {
1672
+ return;
1673
+ }
1674
+ called = true;
1675
+ _valuesSubscriberCount--;
1676
+ unsubscribe();
1677
+ },
1678
+ };
1679
+ }
1680
+ return _getWatch(name, defaultValue, true);
1681
+ };
1682
+ const _subscribe = (props) => {
1683
+ var _a;
1684
+ const needsValues = !!((_a = props.formState) === null || _a === void 0 ? void 0 : _a.values);
1685
+ if (needsValues) {
1686
+ _valuesSubscriberCount++;
1687
+ }
1688
+ const { unsubscribe } = _subjects.state.subscribe({
1689
+ next: (formState) => {
1690
+ if (shouldSubscribeByName(props.name, formState.name, props.exact) &&
1691
+ shouldRenderFormState(formState, props.formState || _proxyFormState, _setFormState, props.reRenderRoot)) {
1692
+ const snapshot = { ..._formValues };
1693
+ props.callback({
1694
+ values: snapshot,
1695
+ ..._formState,
1696
+ ...formState,
1697
+ defaultValues: _defaultValues,
1698
+ });
1699
+ }
1700
+ },
1701
+ });
1702
+ if (!needsValues) {
1703
+ return unsubscribe;
1704
+ }
1705
+ let called = false;
1706
+ return () => {
1707
+ if (called) {
1708
+ return;
1636
1709
  }
1637
- },
1638
- }).unsubscribe;
1710
+ called = true;
1711
+ _valuesSubscriberCount--;
1712
+ unsubscribe();
1713
+ };
1714
+ };
1639
1715
  const subscribe = (props) => {
1640
1716
  _state.mount = true;
1641
1717
  _proxySubscribeFormState = {
@@ -1969,9 +2045,6 @@ function createFormControl(props = {}) {
1969
2045
  _state.watch = !!_options.shouldUnregister;
1970
2046
  _state.keepIsValid = !!keepStateOptions.keepIsValid;
1971
2047
  _state.action = false;
1972
- // Clear errors synchronously to prevent validation errors on subsequent submissions
1973
- // This fixes the issue where form.reset() causes validation errors on subsequent
1974
- // submissions in Next.js 16 with Server Actions
1975
2048
  if (!keepStateOptions.keepErrors) {
1976
2049
  _formState.errors = {};
1977
2050
  }
@@ -2023,8 +2096,6 @@ function createFormControl(props = {}) {
2023
2096
  ? fieldReference.refs[0]
2024
2097
  : fieldReference.ref;
2025
2098
  if (fieldRef.focus) {
2026
- // Use setTimeout to ensure focus happens after any pending state updates
2027
- // This fixes the issue where setFocus doesn't work immediately after setError
2028
2099
  setTimeout(() => {
2029
2100
  fieldRef.focus();
2030
2101
  options.shouldSelect &&
@@ -2118,6 +2189,8 @@ function createFormControl(props = {}) {
2118
2189
  ..._options,
2119
2190
  ...value,
2120
2191
  };
2192
+ _validationModeBeforeSubmit = getValidationModes(_options.mode);
2193
+ _validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
2121
2194
  },
2122
2195
  },
2123
2196
  subscribe,