react-hook-form 7.79.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,CAwwDA"}
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"}
@@ -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
 
@@ -129,6 +128,9 @@ function deepEqual(object1, object2, visited = new WeakMap()) {
129
128
  isEmptyObjectWithCustomPrototype(object2, keys2)) {
130
129
  return Object.is(object1, object2);
131
130
  }
131
+ if (!keys1.length && Array.isArray(object1) !== Array.isArray(object2)) {
132
+ return false;
133
+ }
132
134
  const visitedPairs = visited.get(object1);
133
135
  if (visitedPairs && visitedPairs.has(object2)) {
134
136
  return true;
@@ -137,7 +139,9 @@ function deepEqual(object1, object2, visited = new WeakMap()) {
137
139
  visitedPairs.add(object2);
138
140
  }
139
141
  else {
140
- visited.set(object1, new WeakSet([object2]));
142
+ const ws = new WeakSet();
143
+ ws.add(object2);
144
+ visited.set(object1, ws);
141
145
  }
142
146
  for (const key of keys1) {
143
147
  const val1 = object1[key];
@@ -178,11 +182,13 @@ function extractFormValues(fieldsState, formValues) {
178
182
  return values;
179
183
  }
180
184
 
181
- var isKey = (value) => /^\w*$/.test(value);
185
+ const IS_KEY_RE = /^\w*$/;
186
+ var isKey = (value) => IS_KEY_RE.test(value);
182
187
 
183
188
  var isUndefined = (val) => val === undefined;
184
189
 
185
- var stringToPath = (input) => input.split(/[.[\]'"]/g).filter(Boolean);
190
+ const FIELD_PATH_RE = /[.[\]'"]/;
191
+ var stringToPath = (input) => input.split(FIELD_PATH_RE).filter(Boolean);
186
192
 
187
193
  var get = (object, path, defaultValue) => {
188
194
  if (!path || !isObject(object)) {
@@ -494,12 +500,22 @@ var getValidationModes = (mode) => ({
494
500
  });
495
501
 
496
502
  const ASYNC_FUNCTION = 'AsyncFunction';
497
- var hasPromiseValidation = (fieldReference) => !!fieldReference &&
498
- !!fieldReference.validate &&
499
- !!((isFunction(fieldReference.validate) &&
500
- fieldReference.validate.constructor.name === ASYNC_FUNCTION) ||
501
- (isObject(fieldReference.validate) &&
502
- 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
+ };
503
519
 
504
520
  var hasValidation = (options) => options.mount &&
505
521
  (options.required ||
@@ -514,10 +530,17 @@ var isNameInFieldArray = (names, name) => name
514
530
  .split('.')
515
531
  .some((part, index, arr) => !isNaN(Number(part)) && names.has(arr.slice(0, index).join('.')));
516
532
 
517
- var isWatched = (name, _names, isBlurEvent) => !isBlurEvent &&
518
- (_names.watchAll ||
519
- _names.watch.has(name) ||
520
- [..._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
+ };
521
544
 
522
545
  const iterateFieldsByAction = (fields, action, fieldsNames, abortEarly) => {
523
546
  for (const key of fieldsNames || Object.keys(fields)) {
@@ -585,10 +608,10 @@ function schemaErrorLookup(errors, _fields, name) {
585
608
  var shouldRenderFormState = (formStateData, _proxyFormState, updateFormState, isRoot) => {
586
609
  updateFormState(formStateData);
587
610
  const { name, ...formState } = formStateData;
588
- return (isEmptyObject(formState) ||
589
- (isRoot &&
590
- Object.keys(formState).length >= Object.keys(_proxyFormState).length) ||
591
- 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] ===
592
615
  (!isRoot || VALIDATION_MODE.all)));
593
616
  };
594
617
 
@@ -836,6 +859,7 @@ const defaultOptions = {
836
859
  reValidateMode: VALIDATION_MODE.onChange,
837
860
  shouldFocusError: true,
838
861
  };
862
+ const FORM_ERROR_TYPE = 'form';
839
863
  const DEFAULT_FORM_STATE = {
840
864
  submitCount: 0,
841
865
  isDirty: false,
@@ -883,6 +907,9 @@ function createFormControl(props = {}) {
883
907
  };
884
908
  let delayErrorCallback;
885
909
  let timer = 0;
910
+ let _valuesSubscriberCount = 0;
911
+ let _validationModeBeforeSubmit = getValidationModes(_options.mode);
912
+ let _validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
886
913
  const defaultProxyFormState = {
887
914
  isDirty: false,
888
915
  dirtyFields: false,
@@ -1036,12 +1063,6 @@ function createFormControl(props = {}) {
1036
1063
  : setFieldValue(name, defaultValue);
1037
1064
  if (_state.mount && !_state.action) {
1038
1065
  _setValid();
1039
- // Re-registering a field after a prior unregister puts its key back
1040
- // into _formValues, which can flip isDirty back to false (#13397).
1041
- // Only run when we are currently dirty, otherwise an initial register
1042
- // for a field with no defaultValue would flip isDirty to true. Reset
1043
- // paths repopulate _formValues before re-register, so the key is
1044
- // present then and this branch is skipped (preserves keepDirty).
1045
1066
  if (wasUnsetInFormValues &&
1046
1067
  _formState.isDirty &&
1047
1068
  (_proxyFormState.isDirty || _proxySubscribeFormState.isDirty)) {
@@ -1051,9 +1072,6 @@ function createFormControl(props = {}) {
1051
1072
  _subjects.state.next({ ..._formState });
1052
1073
  }
1053
1074
  }
1054
- // When a watched field is re-registered after being unregistered and
1055
- // its value is restored, trigger a deferred watch broadcast so that
1056
- // components using watch() re-render with the new value.
1057
1075
  if (props.shouldUnregister &&
1058
1076
  wasUnsetInFormValues &&
1059
1077
  !isUndefined(get(_formValues, name)) &&
@@ -1071,12 +1089,13 @@ function createFormControl(props = {}) {
1071
1089
  };
1072
1090
  if (!_options.disabled) {
1073
1091
  if (!isBlurEvent || shouldDirty) {
1092
+ const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
1074
1093
  if (_proxyFormState.isDirty || _proxySubscribeFormState.isDirty) {
1075
1094
  isPreviousDirty = _formState.isDirty;
1076
- _formState.isDirty = output.isDirty = _getDirty();
1095
+ _formState.isDirty = output.isDirty =
1096
+ !isCurrentFieldPristine || _getDirty();
1077
1097
  shouldUpdateField = isPreviousDirty !== output.isDirty;
1078
1098
  }
1079
- const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
1080
1099
  isPreviousDirty = !!get(_formState.dirtyFields, name);
1081
1100
  if (isCurrentFieldPristine !== _formState.isDirty) {
1082
1101
  _formState.dirtyFields = getDirtyFields(_defaultValues, _formValues);
@@ -1275,7 +1294,7 @@ function createFormControl(props = {}) {
1275
1294
  };
1276
1295
  const _getDirty = (name, data) => !_options.disabled &&
1277
1296
  (name && data && set(_formValues, name, data),
1278
- !deepEqual(getValues(), _defaultValues));
1297
+ !deepEqual(_state.mount ? _formValues : _defaultValues, _defaultValues));
1279
1298
  const _getWatch = (names, defaultValue, isGlobal) => generateWatchOutput(names, _names, {
1280
1299
  ...(_state.mount
1281
1300
  ? _formValues
@@ -1286,7 +1305,7 @@ function createFormControl(props = {}) {
1286
1305
  : defaultValue),
1287
1306
  }, isGlobal, defaultValue);
1288
1307
  const _getFieldArray = (name) => compact(get(_state.mount ? _formValues : _defaultValues, name, _options.shouldUnregister ? get(_defaultValues, name, []) : []));
1289
- const setFieldValue = (name, value, options = {}, skipClone = false) => {
1308
+ const setFieldValue = (name, value, options = {}, skipClone = false, skipRender = false) => {
1290
1309
  const field = get(_fields, name);
1291
1310
  let fieldValue = value;
1292
1311
  if (field) {
@@ -1324,7 +1343,7 @@ function createFormControl(props = {}) {
1324
1343
  }
1325
1344
  else {
1326
1345
  fieldReference.ref.value = fieldValue;
1327
- if (!fieldReference.ref.type) {
1346
+ if (!fieldReference.ref.type && !skipRender) {
1328
1347
  _subjects.state.next({
1329
1348
  name,
1330
1349
  values: skipClone ? _formValues : cloneObject(_formValues),
@@ -1334,10 +1353,10 @@ function createFormControl(props = {}) {
1334
1353
  }
1335
1354
  }
1336
1355
  (options.shouldDirty || options.shouldTouch) &&
1337
- updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty, true);
1356
+ updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty, !skipRender);
1338
1357
  options.shouldValidate && trigger(name);
1339
1358
  };
1340
- const setFieldValues = (name, value, options, skipClone = false) => {
1359
+ const setFieldValues = (name, value, options, skipClone = false, skipRender = false) => {
1341
1360
  for (const fieldKey in value) {
1342
1361
  if (!value.hasOwnProperty(fieldKey)) {
1343
1362
  return;
@@ -1349,11 +1368,11 @@ function createFormControl(props = {}) {
1349
1368
  isObject(fieldValue) ||
1350
1369
  (field && !field._f)) &&
1351
1370
  !isDateObject(fieldValue)
1352
- ? setFieldValues(fieldName, fieldValue, options, skipClone)
1353
- : setFieldValue(fieldName, fieldValue, options, skipClone);
1371
+ ? setFieldValues(fieldName, fieldValue, options, skipClone, skipRender)
1372
+ : setFieldValue(fieldName, fieldValue, options, skipClone, skipRender);
1354
1373
  }
1355
1374
  };
1356
- const _setValue = (name, value, options, skipClone) => {
1375
+ const _setValue = (name, value, options, skipClone, skipStateEmit = false) => {
1357
1376
  const field = get(_fields, name);
1358
1377
  const isFieldArray = _names.array.has(name);
1359
1378
  const cloneValue = skipClone ? value : cloneObject(value);
@@ -1373,24 +1392,26 @@ function createFormControl(props = {}) {
1373
1392
  _proxySubscribeFormState.dirtyFields) &&
1374
1393
  options.shouldDirty) {
1375
1394
  _updateDirtyFields();
1376
- _subjects.state.next({
1377
- name,
1378
- dirtyFields: _formState.dirtyFields,
1379
- isDirty: _getDirty(name, cloneValue),
1380
- });
1395
+ if (!skipStateEmit) {
1396
+ _subjects.state.next({
1397
+ name,
1398
+ dirtyFields: _formState.dirtyFields,
1399
+ isDirty: _getDirty(name, cloneValue),
1400
+ });
1401
+ }
1381
1402
  }
1382
1403
  }
1383
1404
  else {
1384
1405
  const isEmpty = (Array.isArray(cloneValue) && !cloneValue.length) ||
1385
1406
  isEmptyObject(cloneValue);
1386
1407
  if (!field || field._f || isNullOrUndefined(cloneValue) || isEmpty) {
1387
- setFieldValue(name, cloneValue, options, skipClone);
1408
+ setFieldValue(name, cloneValue, options, skipClone, skipStateEmit);
1388
1409
  }
1389
1410
  else {
1390
- setFieldValues(name, cloneValue, options, skipClone);
1411
+ setFieldValues(name, cloneValue, options, skipClone, skipStateEmit);
1391
1412
  }
1392
1413
  }
1393
- if (!isValueUnchanged) {
1414
+ if (!isValueUnchanged && !skipStateEmit) {
1394
1415
  const watched = isWatched(name, _names);
1395
1416
  const values = skipClone ? _formValues : cloneObject(_formValues);
1396
1417
  _subjects.state.next({
@@ -1411,13 +1432,13 @@ function createFormControl(props = {}) {
1411
1432
  ...updatedFormValues,
1412
1433
  };
1413
1434
  for (const fieldName of _names.mount) {
1414
- _setValue(fieldName, get(updatedFormValues, fieldName), options, true);
1435
+ _setValue(fieldName, get(updatedFormValues, fieldName), options, true, true);
1415
1436
  }
1416
1437
  _subjects.state.next({
1417
1438
  ..._formState,
1418
1439
  name: undefined,
1419
1440
  type: undefined,
1420
- values: _formValues,
1441
+ ...(_valuesSubscriberCount ? { values: _formValues } : {}),
1421
1442
  });
1422
1443
  if (options.shouldValidate) {
1423
1444
  _setValid();
@@ -1436,8 +1457,6 @@ function createFormControl(props = {}) {
1436
1457
  (isDateObject(fieldValue) && isNaN(fieldValue.getTime())) ||
1437
1458
  deepEqual(fieldValue, get(_formValues, name, fieldValue));
1438
1459
  };
1439
- const validationModeBeforeSubmit = getValidationModes(_options.mode);
1440
- const validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
1441
1460
  if (field) {
1442
1461
  let error;
1443
1462
  let isValid;
@@ -1445,12 +1464,13 @@ function createFormControl(props = {}) {
1445
1464
  ? getFieldValue(field._f)
1446
1465
  : getEventValue(event);
1447
1466
  const isBlurEvent = event.type === EVENTS.BLUR || event.type === EVENTS.FOCUS_OUT;
1448
- const shouldSkipValidation = (!hasValidation(field._f) &&
1467
+ const hasNoValidationEffect = !hasValidation(field._f) &&
1449
1468
  !props.validate &&
1450
1469
  !_options.resolver &&
1451
1470
  !get(_formState.errors, name) &&
1452
- !field._f.deps) ||
1453
- 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);
1454
1474
  const watched = isWatched(name, _names, isBlurEvent);
1455
1475
  set(_formValues, name, fieldValue);
1456
1476
  if (isBlurEvent) {
@@ -1468,10 +1488,13 @@ function createFormControl(props = {}) {
1468
1488
  _subjects.state.next({
1469
1489
  name,
1470
1490
  type: event.type,
1471
- values: cloneObject(_formValues),
1491
+ ...(_valuesSubscriberCount
1492
+ ? { values: cloneObject(_formValues) }
1493
+ : {}),
1472
1494
  });
1473
1495
  if (shouldSkipValidation) {
1474
- if (_proxyFormState.isValid || _proxySubscribeFormState.isValid) {
1496
+ if ((!hasNoValidationEffect || !_formState.isValid) &&
1497
+ (_proxyFormState.isValid || _proxySubscribeFormState.isValid)) {
1475
1498
  if (_options.mode === 'onBlur') {
1476
1499
  if (isBlurEvent) {
1477
1500
  _setValid();
@@ -1606,8 +1629,6 @@ function createFormControl(props = {}) {
1606
1629
  const names = name ? convertToArrayPayload(name) : undefined;
1607
1630
  names === null || names === void 0 ? void 0 : names.forEach((inputName) => unset(_formState.errors, inputName));
1608
1631
  if (names) {
1609
- // Emit for each cleared field with the field name so that
1610
- // shouldSubscribeByName can filter and avoid broad re-renders
1611
1632
  names.forEach((inputName) => {
1612
1633
  _subjects.state.next({
1613
1634
  name: inputName,
@@ -1616,7 +1637,6 @@ function createFormControl(props = {}) {
1616
1637
  });
1617
1638
  }
1618
1639
  else {
1619
- // Clear all errors - emit without name to notify all subscribers
1620
1640
  _subjects.state.next({
1621
1641
  errors: {},
1622
1642
  });
@@ -1625,7 +1645,6 @@ function createFormControl(props = {}) {
1625
1645
  const setError = (name, error, options) => {
1626
1646
  const ref = (get(_fields, name, { _f: {} })._f || {}).ref;
1627
1647
  const currentError = get(_formState.errors, name) || {};
1628
- // Don't override existing error messages elsewhere in the object tree.
1629
1648
  const { ref: currentRef, message, type, ...restOfErrorTree } = currentError;
1630
1649
  set(_formState.errors, name, {
1631
1650
  ...restOfErrorTree,
@@ -1639,26 +1658,60 @@ function createFormControl(props = {}) {
1639
1658
  });
1640
1659
  options && options.shouldFocus && ref && ref.focus && ref.focus();
1641
1660
  };
1642
- const watch = (name, defaultValue) => isFunction(name)
1643
- ? _subjects.state.subscribe({
1644
- next: (payload) => 'values' in payload &&
1645
- name(payload.values || _getWatch(undefined, defaultValue), payload),
1646
- })
1647
- : _getWatch(name, defaultValue, true);
1648
- const _subscribe = (props) => _subjects.state.subscribe({
1649
- next: (formState) => {
1650
- if (shouldSubscribeByName(props.name, formState.name, props.exact) &&
1651
- shouldRenderFormState(formState, props.formState || _proxyFormState, _setFormState, props.reRenderRoot)) {
1652
- const snapshot = { ..._formValues };
1653
- props.callback({
1654
- values: snapshot,
1655
- ..._formState,
1656
- ...formState,
1657
- defaultValues: _defaultValues,
1658
- });
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;
1659
1709
  }
1660
- },
1661
- }).unsubscribe;
1710
+ called = true;
1711
+ _valuesSubscriberCount--;
1712
+ unsubscribe();
1713
+ };
1714
+ };
1662
1715
  const subscribe = (props) => {
1663
1716
  _state.mount = true;
1664
1717
  _proxySubscribeFormState = {
@@ -1992,9 +2045,6 @@ function createFormControl(props = {}) {
1992
2045
  _state.watch = !!_options.shouldUnregister;
1993
2046
  _state.keepIsValid = !!keepStateOptions.keepIsValid;
1994
2047
  _state.action = false;
1995
- // Clear errors synchronously to prevent validation errors on subsequent submissions
1996
- // This fixes the issue where form.reset() causes validation errors on subsequent
1997
- // submissions in Next.js 16 with Server Actions
1998
2048
  if (!keepStateOptions.keepErrors) {
1999
2049
  _formState.errors = {};
2000
2050
  }
@@ -2046,8 +2096,6 @@ function createFormControl(props = {}) {
2046
2096
  ? fieldReference.refs[0]
2047
2097
  : fieldReference.ref;
2048
2098
  if (fieldRef.focus) {
2049
- // Use setTimeout to ensure focus happens after any pending state updates
2050
- // This fixes the issue where setFocus doesn't work immediately after setError
2051
2099
  setTimeout(() => {
2052
2100
  fieldRef.focus();
2053
2101
  options.shouldSelect &&
@@ -2141,6 +2189,8 @@ function createFormControl(props = {}) {
2141
2189
  ..._options,
2142
2190
  ...value,
2143
2191
  };
2192
+ _validationModeBeforeSubmit = getValidationModes(_options.mode);
2193
+ _validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
2144
2194
  },
2145
2195
  },
2146
2196
  subscribe,