react-hook-form 7.53.1 → 7.54.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.
Files changed (100) hide show
  1. package/README.md +6 -0
  2. package/dist/index.cjs.js +1 -1
  3. package/dist/index.cjs.js.map +1 -1
  4. package/dist/index.esm.mjs +108 -88
  5. package/dist/index.esm.mjs.map +1 -1
  6. package/dist/index.umd.js +1 -1
  7. package/dist/index.umd.js.map +1 -1
  8. package/dist/logic/createFormControl.d.ts.map +1 -1
  9. package/dist/logic/hasPromiseValidation.d.ts.map +1 -1
  10. package/dist/react-server.esm.mjs +1 -1
  11. package/dist/react-server.esm.mjs.map +1 -1
  12. package/dist/useController.d.ts.map +1 -1
  13. package/dist/useFieldArray.d.ts.map +1 -1
  14. package/dist/useForm.d.ts.map +1 -1
  15. package/dist/useFormState.d.ts.map +1 -1
  16. package/dist/utils/cloneObject.d.ts.map +1 -1
  17. package/package.json +1 -1
  18. package/dist/__tests__/controller.server.test.d.ts +0 -2
  19. package/dist/__tests__/controller.server.test.d.ts.map +0 -1
  20. package/dist/__tests__/controller.test.d.ts +0 -2
  21. package/dist/__tests__/controller.test.d.ts.map +0 -1
  22. package/dist/__tests__/form.test.d.ts +0 -2
  23. package/dist/__tests__/form.test.d.ts.map +0 -1
  24. package/dist/__tests__/logic/validateField.test.d.ts +0 -2
  25. package/dist/__tests__/logic/validateField.test.d.ts.map +0 -1
  26. package/dist/__tests__/type.test.d.ts +0 -2
  27. package/dist/__tests__/type.test.d.ts.map +0 -1
  28. package/dist/__tests__/useController.test.d.ts +0 -2
  29. package/dist/__tests__/useController.test.d.ts.map +0 -1
  30. package/dist/__tests__/useFieldArray/append.test.d.ts +0 -2
  31. package/dist/__tests__/useFieldArray/append.test.d.ts.map +0 -1
  32. package/dist/__tests__/useFieldArray/focus.test.d.ts +0 -2
  33. package/dist/__tests__/useFieldArray/focus.test.d.ts.map +0 -1
  34. package/dist/__tests__/useFieldArray/insert.test.d.ts +0 -2
  35. package/dist/__tests__/useFieldArray/insert.test.d.ts.map +0 -1
  36. package/dist/__tests__/useFieldArray/move.test.d.ts +0 -2
  37. package/dist/__tests__/useFieldArray/move.test.d.ts.map +0 -1
  38. package/dist/__tests__/useFieldArray/prepend.test.d.ts +0 -2
  39. package/dist/__tests__/useFieldArray/prepend.test.d.ts.map +0 -1
  40. package/dist/__tests__/useFieldArray/remove.test.d.ts +0 -2
  41. package/dist/__tests__/useFieldArray/remove.test.d.ts.map +0 -1
  42. package/dist/__tests__/useFieldArray/replace.test.d.ts +0 -2
  43. package/dist/__tests__/useFieldArray/replace.test.d.ts.map +0 -1
  44. package/dist/__tests__/useFieldArray/swap.test.d.ts +0 -2
  45. package/dist/__tests__/useFieldArray/swap.test.d.ts.map +0 -1
  46. package/dist/__tests__/useFieldArray/update.test.d.ts +0 -2
  47. package/dist/__tests__/useFieldArray/update.test.d.ts.map +0 -1
  48. package/dist/__tests__/useFieldArray.test.d.ts +0 -2
  49. package/dist/__tests__/useFieldArray.test.d.ts.map +0 -1
  50. package/dist/__tests__/useForm/clearErrors.test.d.ts +0 -2
  51. package/dist/__tests__/useForm/clearErrors.test.d.ts.map +0 -1
  52. package/dist/__tests__/useForm/formState.test.d.ts +0 -2
  53. package/dist/__tests__/useForm/formState.test.d.ts.map +0 -1
  54. package/dist/__tests__/useForm/getFieldState.test.d.ts +0 -2
  55. package/dist/__tests__/useForm/getFieldState.test.d.ts.map +0 -1
  56. package/dist/__tests__/useForm/getValues.test.d.ts +0 -2
  57. package/dist/__tests__/useForm/getValues.test.d.ts.map +0 -1
  58. package/dist/__tests__/useForm/handleSubmit.test.d.ts +0 -2
  59. package/dist/__tests__/useForm/handleSubmit.test.d.ts.map +0 -1
  60. package/dist/__tests__/useForm/register.test.d.ts +0 -2
  61. package/dist/__tests__/useForm/register.test.d.ts.map +0 -1
  62. package/dist/__tests__/useForm/reset.test.d.ts +0 -2
  63. package/dist/__tests__/useForm/reset.test.d.ts.map +0 -1
  64. package/dist/__tests__/useForm/resetField.test.d.ts +0 -2
  65. package/dist/__tests__/useForm/resetField.test.d.ts.map +0 -1
  66. package/dist/__tests__/useForm/resolver.test.d.ts +0 -2
  67. package/dist/__tests__/useForm/resolver.test.d.ts.map +0 -1
  68. package/dist/__tests__/useForm/setError.test.d.ts +0 -2
  69. package/dist/__tests__/useForm/setError.test.d.ts.map +0 -1
  70. package/dist/__tests__/useForm/setValue.test.d.ts +0 -2
  71. package/dist/__tests__/useForm/setValue.test.d.ts.map +0 -1
  72. package/dist/__tests__/useForm/trigger.test.d.ts +0 -2
  73. package/dist/__tests__/useForm/trigger.test.d.ts.map +0 -1
  74. package/dist/__tests__/useForm/unregister.test.d.ts +0 -2
  75. package/dist/__tests__/useForm/unregister.test.d.ts.map +0 -1
  76. package/dist/__tests__/useForm/watch.test.d.ts +0 -2
  77. package/dist/__tests__/useForm/watch.test.d.ts.map +0 -1
  78. package/dist/__tests__/useForm.server.test.d.ts +0 -2
  79. package/dist/__tests__/useForm.server.test.d.ts.map +0 -1
  80. package/dist/__tests__/useForm.test.d.ts +0 -2
  81. package/dist/__tests__/useForm.test.d.ts.map +0 -1
  82. package/dist/__tests__/useFormContext.server.test.d.ts +0 -2
  83. package/dist/__tests__/useFormContext.server.test.d.ts.map +0 -1
  84. package/dist/__tests__/useFormContext.test.d.ts +0 -2
  85. package/dist/__tests__/useFormContext.test.d.ts.map +0 -1
  86. package/dist/__tests__/useFormState.test.d.ts +0 -2
  87. package/dist/__tests__/useFormState.test.d.ts.map +0 -1
  88. package/dist/__tests__/useWatch.test.d.ts +0 -2
  89. package/dist/__tests__/useWatch.test.d.ts.map +0 -1
  90. package/dist/logic/focusFieldBy.d.ts +0 -8
  91. package/dist/logic/focusFieldBy.d.ts.map +0 -1
  92. package/dist/tsdoc-metadata.json +0 -11
  93. package/dist/utils/fillBooleanArray.d.ts +0 -3
  94. package/dist/utils/fillBooleanArray.d.ts.map +0 -1
  95. package/dist/utils/isSelectInput.d.ts +0 -4
  96. package/dist/utils/isSelectInput.d.ts.map +0 -1
  97. package/dist/utils/objectHasTruthyValue.d.ts +0 -3
  98. package/dist/utils/objectHasTruthyValue.d.ts.map +0 -1
  99. package/dist/utils/omit.d.ts +0 -6
  100. package/dist/utils/omit.d.ts.map +0 -1
@@ -34,13 +34,14 @@ var isWeb = typeof window !== 'undefined' &&
34
34
  function cloneObject(data) {
35
35
  let copy;
36
36
  const isArray = Array.isArray(data);
37
+ const isFileListInstance = typeof FileList !== 'undefined' ? data instanceof FileList : false;
37
38
  if (data instanceof Date) {
38
39
  copy = new Date(data);
39
40
  }
40
41
  else if (data instanceof Set) {
41
42
  copy = new Set(data);
42
43
  }
43
- else if (!(isWeb && (data instanceof Blob || data instanceof FileList)) &&
44
+ else if (!(isWeb && (data instanceof Blob || isFileListInstance)) &&
44
45
  (isArray || isObject(data))) {
45
46
  copy = isArray ? [] : {};
46
47
  if (!isArray && !isPlainObject(data)) {
@@ -99,7 +100,7 @@ var set = (object, path, value) => {
99
100
  ? []
100
101
  : {};
101
102
  }
102
- if (key === '__proto__') {
103
+ if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
103
104
  return;
104
105
  }
105
106
  object[key] = newValue;
@@ -318,7 +319,7 @@ function useFormState(props) {
318
319
  _mounted.current = false;
319
320
  };
320
321
  }, [control]);
321
- return getProxyFormState(formState, control, _localProxyFormState.current, false);
322
+ return React.useMemo(() => getProxyFormState(formState, control, _localProxyFormState.current, false), [formState, control]);
322
323
  }
323
324
 
324
325
  var isString = (value) => typeof value === 'string';
@@ -414,6 +415,67 @@ function useController(props) {
414
415
  value,
415
416
  ...(isBoolean(props.disabled) ? { disabled: props.disabled } : {}),
416
417
  }));
418
+ const fieldState = React.useMemo(() => Object.defineProperties({}, {
419
+ invalid: {
420
+ enumerable: true,
421
+ get: () => !!get(formState.errors, name),
422
+ },
423
+ isDirty: {
424
+ enumerable: true,
425
+ get: () => !!get(formState.dirtyFields, name),
426
+ },
427
+ isTouched: {
428
+ enumerable: true,
429
+ get: () => !!get(formState.touchedFields, name),
430
+ },
431
+ isValidating: {
432
+ enumerable: true,
433
+ get: () => !!get(formState.validatingFields, name),
434
+ },
435
+ error: {
436
+ enumerable: true,
437
+ get: () => get(formState.errors, name),
438
+ },
439
+ }), [formState, name]);
440
+ const field = React.useMemo(() => ({
441
+ name,
442
+ value,
443
+ ...(isBoolean(disabled) || formState.disabled
444
+ ? { disabled: formState.disabled || disabled }
445
+ : {}),
446
+ onChange: (event) => _registerProps.current.onChange({
447
+ target: {
448
+ value: getEventValue(event),
449
+ name: name,
450
+ },
451
+ type: EVENTS.CHANGE,
452
+ }),
453
+ onBlur: () => _registerProps.current.onBlur({
454
+ target: {
455
+ value: get(control._formValues, name),
456
+ name: name,
457
+ },
458
+ type: EVENTS.BLUR,
459
+ }),
460
+ ref: (elm) => {
461
+ const field = get(control._fields, name);
462
+ if (field && elm) {
463
+ field._f.ref = {
464
+ focus: () => elm.focus(),
465
+ select: () => elm.select(),
466
+ setCustomValidity: (message) => elm.setCustomValidity(message),
467
+ reportValidity: () => elm.reportValidity(),
468
+ };
469
+ }
470
+ },
471
+ }), [
472
+ name,
473
+ control._formValues,
474
+ disabled,
475
+ formState.disabled,
476
+ value,
477
+ control._fields,
478
+ ]);
417
479
  React.useEffect(() => {
418
480
  const _shouldUnregisterField = control._options.shouldUnregister || shouldUnregister;
419
481
  const updateMounted = (name, value) => {
@@ -439,7 +501,7 @@ function useController(props) {
439
501
  };
440
502
  }, [name, control, isArrayField, shouldUnregister]);
441
503
  React.useEffect(() => {
442
- if (get(control._fields, name)) {
504
+ if (isBoolean(disabled) && get(control._fields, name)) {
443
505
  control._updateDisabledField({
444
506
  disabled,
445
507
  fields: control._fields,
@@ -448,63 +510,11 @@ function useController(props) {
448
510
  });
449
511
  }
450
512
  }, [disabled, name, control]);
451
- return {
452
- field: {
453
- name,
454
- value,
455
- ...(isBoolean(disabled) || formState.disabled
456
- ? { disabled: formState.disabled || disabled }
457
- : {}),
458
- onChange: React.useCallback((event) => _registerProps.current.onChange({
459
- target: {
460
- value: getEventValue(event),
461
- name: name,
462
- },
463
- type: EVENTS.CHANGE,
464
- }), [name]),
465
- onBlur: React.useCallback(() => _registerProps.current.onBlur({
466
- target: {
467
- value: get(control._formValues, name),
468
- name: name,
469
- },
470
- type: EVENTS.BLUR,
471
- }), [name, control]),
472
- ref: React.useCallback((elm) => {
473
- const field = get(control._fields, name);
474
- if (field && elm) {
475
- field._f.ref = {
476
- focus: () => elm.focus(),
477
- select: () => elm.select(),
478
- setCustomValidity: (message) => elm.setCustomValidity(message),
479
- reportValidity: () => elm.reportValidity(),
480
- };
481
- }
482
- }, [control._fields, name]),
483
- },
513
+ return React.useMemo(() => ({
514
+ field,
484
515
  formState,
485
- fieldState: Object.defineProperties({}, {
486
- invalid: {
487
- enumerable: true,
488
- get: () => !!get(formState.errors, name),
489
- },
490
- isDirty: {
491
- enumerable: true,
492
- get: () => !!get(formState.dirtyFields, name),
493
- },
494
- isTouched: {
495
- enumerable: true,
496
- get: () => !!get(formState.touchedFields, name),
497
- },
498
- isValidating: {
499
- enumerable: true,
500
- get: () => !!get(formState.validatingFields, name),
501
- },
502
- error: {
503
- enumerable: true,
504
- get: () => get(formState.errors, name),
505
- },
506
- }),
507
- };
516
+ fieldState,
517
+ }), [field, formState, fieldState]);
508
518
  }
509
519
 
510
520
  /**
@@ -554,7 +564,7 @@ const Controller = (props) => props.render(useController(props));
554
564
  const flatten = (obj) => {
555
565
  const output = {};
556
566
  for (const key of Object.keys(obj)) {
557
- if (isObjectType(obj[key])) {
567
+ if (isObjectType(obj[key]) && obj[key] !== null) {
558
568
  const nested = flatten(obj[key]);
559
569
  for (const nestedKey of Object.keys(nested)) {
560
570
  output[`${key}.${nestedKey}`] = nested[nestedKey];
@@ -1121,7 +1131,7 @@ var updateAt = (fieldValues, index, value) => {
1121
1131
  */
1122
1132
  function useFieldArray(props) {
1123
1133
  const methods = useFormContext();
1124
- const { control = methods.control, name, keyName = 'id', shouldUnregister, } = props;
1134
+ const { control = methods.control, name, keyName = 'id', shouldUnregister, rules, } = props;
1125
1135
  const [fields, setFields] = React.useState(control._getFieldArray(name));
1126
1136
  const ids = React.useRef(control._getFieldArray(name).map(generateId));
1127
1137
  const _fieldIds = React.useRef(fields);
@@ -1130,8 +1140,8 @@ function useFieldArray(props) {
1130
1140
  _name.current = name;
1131
1141
  _fieldIds.current = fields;
1132
1142
  control._names.array.add(name);
1133
- props.rules &&
1134
- control.register(name, props.rules);
1143
+ rules &&
1144
+ control.register(name, rules);
1135
1145
  useSubscribe({
1136
1146
  next: ({ values, name: fieldArrayName, }) => {
1137
1147
  if (fieldArrayName === _name.current || !fieldArrayName) {
@@ -1175,6 +1185,8 @@ function useFieldArray(props) {
1175
1185
  ids.current = removeArrayAt(ids.current, index);
1176
1186
  updateValues(updatedFieldArrayValues);
1177
1187
  setFields(updatedFieldArrayValues);
1188
+ !Array.isArray(get(control._fields, name)) &&
1189
+ set(control._fields, name, undefined);
1178
1190
  control._updateFieldArray(name, updatedFieldArrayValues, removeArrayAt, {
1179
1191
  argA: index,
1180
1192
  });
@@ -1489,7 +1501,8 @@ var getRuleValue = (rule) => isUndefined(rule)
1489
1501
  : rule;
1490
1502
 
1491
1503
  const ASYNC_FUNCTION = 'AsyncFunction';
1492
- var hasPromiseValidation = (fieldReference) => (!fieldReference || !fieldReference.validate) &&
1504
+ var hasPromiseValidation = (fieldReference) => !!fieldReference &&
1505
+ !!fieldReference.validate &&
1493
1506
  !!((isFunction(fieldReference.validate) &&
1494
1507
  fieldReference.validate.constructor.name === ASYNC_FUNCTION) ||
1495
1508
  (isObject(fieldReference.validate) &&
@@ -1618,7 +1631,7 @@ function createFormControl(props = {}) {
1618
1631
  timer = setTimeout(callback, wait);
1619
1632
  };
1620
1633
  const _updateValid = async (shouldUpdateValid) => {
1621
- if (!props.disabled && (_proxyFormState.isValid || shouldUpdateValid)) {
1634
+ if (!_options.disabled && (_proxyFormState.isValid || shouldUpdateValid)) {
1622
1635
  const isValid = _options.resolver
1623
1636
  ? isEmptyObject((await _executeSchema()).errors)
1624
1637
  : await executeBuiltInValidation(_fields, true);
@@ -1630,7 +1643,7 @@ function createFormControl(props = {}) {
1630
1643
  }
1631
1644
  };
1632
1645
  const _updateIsValidating = (names, isValidating) => {
1633
- if (!props.disabled &&
1646
+ if (!_options.disabled &&
1634
1647
  (_proxyFormState.isValidating || _proxyFormState.validatingFields)) {
1635
1648
  (names || Array.from(_names.mount)).forEach((name) => {
1636
1649
  if (name) {
@@ -1646,7 +1659,7 @@ function createFormControl(props = {}) {
1646
1659
  }
1647
1660
  };
1648
1661
  const _updateFieldArray = (name, values = [], method, args, shouldSetValues = true, shouldUpdateFieldsAndState = true) => {
1649
- if (args && method && !props.disabled) {
1662
+ if (args && method && !_options.disabled) {
1650
1663
  _state.action = true;
1651
1664
  if (shouldUpdateFieldsAndState && Array.isArray(get(_fields, name))) {
1652
1665
  const fieldValues = method(get(_fields, name), args.argA, args.argB);
@@ -1710,7 +1723,7 @@ function createFormControl(props = {}) {
1710
1723
  const output = {
1711
1724
  name,
1712
1725
  };
1713
- if (!props.disabled) {
1726
+ if (!_options.disabled) {
1714
1727
  const disabledField = !!(get(_fields, name) &&
1715
1728
  get(_fields, name)._f &&
1716
1729
  get(_fields, name)._f.disabled);
@@ -1751,9 +1764,9 @@ function createFormControl(props = {}) {
1751
1764
  const shouldUpdateValid = _proxyFormState.isValid &&
1752
1765
  isBoolean(isValid) &&
1753
1766
  _formState.isValid !== isValid;
1754
- if (props.delayError && error) {
1767
+ if (_options.delayError && error) {
1755
1768
  delayErrorCallback = debounce(() => updateErrors(name, error));
1756
- delayErrorCallback(props.delayError);
1769
+ delayErrorCallback(_options.delayError);
1757
1770
  }
1758
1771
  else {
1759
1772
  clearTimeout(timer);
@@ -1846,7 +1859,7 @@ function createFormControl(props = {}) {
1846
1859
  }
1847
1860
  _names.unMount = new Set();
1848
1861
  };
1849
- const _getDirty = (name, data) => !props.disabled &&
1862
+ const _getDirty = (name, data) => !_options.disabled &&
1850
1863
  (name && data && set(_formValues, name, data),
1851
1864
  !deepEqual(getValues(), _defaultValues));
1852
1865
  const _getWatch = (names, defaultValue, isGlobal) => generateWatchOutput(names, _names, {
@@ -1858,7 +1871,7 @@ function createFormControl(props = {}) {
1858
1871
  ? { [names]: defaultValue }
1859
1872
  : defaultValue),
1860
1873
  }, isGlobal, defaultValue);
1861
- const _getFieldArray = (name) => compact(get(_state.mount ? _formValues : _defaultValues, name, props.shouldUnregister ? get(_defaultValues, name, []) : []));
1874
+ const _getFieldArray = (name) => compact(get(_state.mount ? _formValues : _defaultValues, name, _options.shouldUnregister ? get(_defaultValues, name, []) : []));
1862
1875
  const setFieldValue = (name, value, options = {}) => {
1863
1876
  const field = get(_fields, name);
1864
1877
  let fieldValue = value;
@@ -1991,7 +2004,7 @@ function createFormControl(props = {}) {
1991
2004
  });
1992
2005
  if (shouldSkipValidation) {
1993
2006
  if (_proxyFormState.isValid) {
1994
- if (props.mode === 'onBlur') {
2007
+ if (_options.mode === 'onBlur') {
1995
2008
  if (isBlurEvent) {
1996
2009
  _updateValid();
1997
2010
  }
@@ -2156,13 +2169,15 @@ function createFormControl(props = {}) {
2156
2169
  : isUndefined(value)
2157
2170
  ? getFieldValue(field ? field._f : get(fields, name)._f)
2158
2171
  : value;
2159
- set(_formValues, name, inputValue);
2172
+ if (disabled || (!disabled && !isUndefined(inputValue))) {
2173
+ set(_formValues, name, inputValue);
2174
+ }
2160
2175
  updateTouchAndDirty(name, inputValue, false, false, true);
2161
2176
  }
2162
2177
  };
2163
2178
  const register = (name, options = {}) => {
2164
2179
  let field = get(_fields, name);
2165
- const disabledIsDefined = isBoolean(options.disabled) || isBoolean(props.disabled);
2180
+ const disabledIsDefined = isBoolean(options.disabled) || isBoolean(_options.disabled);
2166
2181
  set(_fields, name, {
2167
2182
  ...(field || {}),
2168
2183
  _f: {
@@ -2178,7 +2193,7 @@ function createFormControl(props = {}) {
2178
2193
  field,
2179
2194
  disabled: isBoolean(options.disabled)
2180
2195
  ? options.disabled
2181
- : props.disabled,
2196
+ : _options.disabled,
2182
2197
  name,
2183
2198
  value: options.value,
2184
2199
  });
@@ -2188,7 +2203,7 @@ function createFormControl(props = {}) {
2188
2203
  }
2189
2204
  return {
2190
2205
  ...(disabledIsDefined
2191
- ? { disabled: options.disabled || props.disabled }
2206
+ ? { disabled: options.disabled || _options.disabled }
2192
2207
  : {}),
2193
2208
  ...(_options.progressive
2194
2209
  ? {
@@ -2272,6 +2287,12 @@ function createFormControl(props = {}) {
2272
2287
  e.preventDefault && e.preventDefault();
2273
2288
  e.persist && e.persist();
2274
2289
  }
2290
+ if (_options.disabled) {
2291
+ if (onInvalid) {
2292
+ await onInvalid({ ..._formState.errors }, e);
2293
+ }
2294
+ return;
2295
+ }
2275
2296
  let fieldValues = cloneObject(_formValues);
2276
2297
  _subjects.state.next({
2277
2298
  isSubmitting: true,
@@ -2379,7 +2400,7 @@ function createFormControl(props = {}) {
2379
2400
  }
2380
2401
  _fields = {};
2381
2402
  }
2382
- _formValues = props.shouldUnregister
2403
+ _formValues = _options.shouldUnregister
2383
2404
  ? keepStateOptions.keepDefaultValues
2384
2405
  ? cloneObject(_defaultValues)
2385
2406
  : {}
@@ -2403,7 +2424,7 @@ function createFormControl(props = {}) {
2403
2424
  !_proxyFormState.isValid ||
2404
2425
  !!keepStateOptions.keepIsValid ||
2405
2426
  !!keepStateOptions.keepDirtyValues;
2406
- _state.watch = !!props.shouldUnregister;
2427
+ _state.watch = !!_options.shouldUnregister;
2407
2428
  _subjects.state.next({
2408
2429
  submitCount: keepStateOptions.keepSubmitCount
2409
2430
  ? _formState.submitCount
@@ -2450,7 +2471,9 @@ function createFormControl(props = {}) {
2450
2471
  : fieldReference.ref;
2451
2472
  if (fieldRef.focus) {
2452
2473
  fieldRef.focus();
2453
- options.shouldSelect && fieldRef.select();
2474
+ options.shouldSelect &&
2475
+ isFunction(fieldRef.select) &&
2476
+ fieldRef.select();
2454
2477
  }
2455
2478
  }
2456
2479
  };
@@ -2651,13 +2674,10 @@ function useForm(props = {}) {
2651
2674
  values: control._getWatch(),
2652
2675
  });
2653
2676
  }, [props.shouldUnregister, control]);
2654
- React.useEffect(() => {
2655
- if (_formControl.current) {
2656
- _formControl.current.watch = _formControl.current.watch.bind({});
2657
- }
2658
- }, [formState]);
2659
- _formControl.current.formState = getProxyFormState(formState, control);
2660
- return _formControl.current;
2677
+ return React.useMemo(() => ({
2678
+ ..._formControl.current,
2679
+ formState: getProxyFormState(formState, control),
2680
+ }), [formState, control]);
2661
2681
  }
2662
2682
 
2663
2683
  export { Controller, Form, FormProvider, appendErrors, get, set, useController, useFieldArray, useForm, useFormContext, useFormState, useWatch };