react-hook-form 8.0.0-beta.1 → 8.0.0-beta.2

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 (261) hide show
  1. package/README.md +16 -29
  2. package/dist/constants.d.ts +5 -0
  3. package/dist/constants.d.ts.map +1 -1
  4. package/dist/form.d.ts.map +1 -1
  5. package/dist/index.cjs.js +1 -1
  6. package/dist/index.cjs.js.map +1 -1
  7. package/dist/index.esm.mjs +395 -153
  8. package/dist/index.esm.mjs.map +1 -1
  9. package/dist/index.umd.js +1 -1
  10. package/dist/index.umd.js.map +1 -1
  11. package/dist/logic/createFormControl.d.ts +13 -0
  12. package/dist/logic/createFormControl.d.ts.map +1 -1
  13. package/dist/logic/getDirtyFields.d.ts.map +1 -1
  14. package/dist/logic/{isNameInFieldArray.d.ts → getFieldArrayParentNames.d.ts} +2 -2
  15. package/dist/logic/getFieldArrayParentNames.d.ts.map +1 -0
  16. package/dist/logic/getProxyFormState.d.ts.map +1 -1
  17. package/dist/logic/getResolverOptions.d.ts +2 -2
  18. package/dist/logic/hasValidation.d.ts +1 -1
  19. package/dist/logic/shouldRenderFormState.d.ts.map +1 -1
  20. package/dist/logic/updateFieldArrayRootError.d.ts.map +1 -1
  21. package/dist/logic/validateField.d.ts.map +1 -1
  22. package/dist/react-server.esm.mjs +310 -76
  23. package/dist/react-server.esm.mjs.map +1 -1
  24. package/dist/types/errors.d.ts +1 -0
  25. package/dist/types/errors.d.ts.map +1 -1
  26. package/dist/types/form.d.ts +12 -5
  27. package/dist/types/form.d.ts.map +1 -1
  28. package/dist/types/path/eager.d.ts +1 -1
  29. package/dist/types/path/eager.d.ts.map +1 -1
  30. package/dist/types/utils.d.ts +2 -2
  31. package/dist/types/validator.d.ts +13 -1
  32. package/dist/types/validator.d.ts.map +1 -1
  33. package/dist/useFieldArray.d.ts.map +1 -1
  34. package/dist/useForm.d.ts.map +1 -1
  35. package/dist/useFormContext.d.ts.map +1 -1
  36. package/dist/useFormState.d.ts.map +1 -1
  37. package/dist/utils/deepEqual.d.ts +1 -1
  38. package/dist/utils/deepEqual.d.ts.map +1 -1
  39. package/dist/utils/unset.d.ts.map +1 -1
  40. package/dist/watch.d.ts +1 -1
  41. package/dist/watch.d.ts.map +1 -1
  42. package/package.json +25 -26
  43. package/dist/__tests__/controller.server.test.d.ts +0 -2
  44. package/dist/__tests__/controller.server.test.d.ts.map +0 -1
  45. package/dist/__tests__/controller.test.d.ts +0 -2
  46. package/dist/__tests__/controller.test.d.ts.map +0 -1
  47. package/dist/__tests__/form.test.d.ts +0 -2
  48. package/dist/__tests__/form.test.d.ts.map +0 -1
  49. package/dist/__tests__/formStateSubscribe.server.test.d.ts +0 -2
  50. package/dist/__tests__/formStateSubscribe.server.test.d.ts.map +0 -1
  51. package/dist/__tests__/formStateSubscribe.test.d.ts +0 -2
  52. package/dist/__tests__/formStateSubscribe.test.d.ts.map +0 -1
  53. package/dist/__tests__/isPlainObject.test.d.ts +0 -2
  54. package/dist/__tests__/isPlainObject.test.d.ts.map +0 -1
  55. package/dist/__tests__/logic/appendErrors.test.d.ts +0 -2
  56. package/dist/__tests__/logic/appendErrors.test.d.ts.map +0 -1
  57. package/dist/__tests__/logic/createFormControl.test.d.ts +0 -2
  58. package/dist/__tests__/logic/createFormControl.test.d.ts.map +0 -1
  59. package/dist/__tests__/logic/generateId.test.d.ts +0 -2
  60. package/dist/__tests__/logic/generateId.test.d.ts.map +0 -1
  61. package/dist/__tests__/logic/getCheckboxValue.test.d.ts +0 -2
  62. package/dist/__tests__/logic/getCheckboxValue.test.d.ts.map +0 -1
  63. package/dist/__tests__/logic/getDirtyFields.test.d.ts +0 -2
  64. package/dist/__tests__/logic/getDirtyFields.test.d.ts.map +0 -1
  65. package/dist/__tests__/logic/getEventValue.test.d.ts +0 -2
  66. package/dist/__tests__/logic/getEventValue.test.d.ts.map +0 -1
  67. package/dist/__tests__/logic/getFieldValue.test.d.ts +0 -2
  68. package/dist/__tests__/logic/getFieldValue.test.d.ts.map +0 -1
  69. package/dist/__tests__/logic/getFieldValueAs.test.d.ts +0 -2
  70. package/dist/__tests__/logic/getFieldValueAs.test.d.ts.map +0 -1
  71. package/dist/__tests__/logic/getFocusFieldName.test.d.ts +0 -2
  72. package/dist/__tests__/logic/getFocusFieldName.test.d.ts.map +0 -1
  73. package/dist/__tests__/logic/getNodeParentName.test.d.ts +0 -2
  74. package/dist/__tests__/logic/getNodeParentName.test.d.ts.map +0 -1
  75. package/dist/__tests__/logic/getRadioValue.test.d.ts +0 -2
  76. package/dist/__tests__/logic/getRadioValue.test.d.ts.map +0 -1
  77. package/dist/__tests__/logic/getResolverOptions.test.d.ts +0 -2
  78. package/dist/__tests__/logic/getResolverOptions.test.d.ts.map +0 -1
  79. package/dist/__tests__/logic/getRuleValue.test.d.ts +0 -2
  80. package/dist/__tests__/logic/getRuleValue.test.d.ts.map +0 -1
  81. package/dist/__tests__/logic/getValidateError.test.d.ts +0 -2
  82. package/dist/__tests__/logic/getValidateError.test.d.ts.map +0 -1
  83. package/dist/__tests__/logic/getValidationModes.test.d.ts +0 -2
  84. package/dist/__tests__/logic/getValidationModes.test.d.ts.map +0 -1
  85. package/dist/__tests__/logic/getValueAndMessage.test.d.ts +0 -2
  86. package/dist/__tests__/logic/getValueAndMessage.test.d.ts.map +0 -1
  87. package/dist/__tests__/logic/hasPromiseValidation.test.d.ts +0 -2
  88. package/dist/__tests__/logic/hasPromiseValidation.test.d.ts.map +0 -1
  89. package/dist/__tests__/logic/hasValidation.test.d.ts +0 -2
  90. package/dist/__tests__/logic/hasValidation.test.d.ts.map +0 -1
  91. package/dist/__tests__/logic/isNameInFieldArray.test.d.ts +0 -2
  92. package/dist/__tests__/logic/isNameInFieldArray.test.d.ts.map +0 -1
  93. package/dist/__tests__/logic/isWatched.test.d.ts +0 -2
  94. package/dist/__tests__/logic/isWatched.test.d.ts.map +0 -1
  95. package/dist/__tests__/logic/iterateFieldsByAction.test.d.ts +0 -2
  96. package/dist/__tests__/logic/iterateFieldsByAction.test.d.ts.map +0 -1
  97. package/dist/__tests__/logic/schemaErrorLookup.test.d.ts +0 -2
  98. package/dist/__tests__/logic/schemaErrorLookup.test.d.ts.map +0 -1
  99. package/dist/__tests__/logic/shouldRenderFormState.test.d.ts +0 -2
  100. package/dist/__tests__/logic/shouldRenderFormState.test.d.ts.map +0 -1
  101. package/dist/__tests__/logic/shouldSubscribeByName.test.d.ts +0 -2
  102. package/dist/__tests__/logic/shouldSubscribeByName.test.d.ts.map +0 -1
  103. package/dist/__tests__/logic/skipValidation.test.d.ts +0 -2
  104. package/dist/__tests__/logic/skipValidation.test.d.ts.map +0 -1
  105. package/dist/__tests__/logic/unsetEmptyArray.test.d.ts +0 -2
  106. package/dist/__tests__/logic/unsetEmptyArray.test.d.ts.map +0 -1
  107. package/dist/__tests__/logic/validateField.test.d.ts +0 -2
  108. package/dist/__tests__/logic/validateField.test.d.ts.map +0 -1
  109. package/dist/__tests__/type.test.d.ts +0 -2
  110. package/dist/__tests__/type.test.d.ts.map +0 -1
  111. package/dist/__tests__/useController.test.d.ts +0 -2
  112. package/dist/__tests__/useController.test.d.ts.map +0 -1
  113. package/dist/__tests__/useFieldArray/append.test.d.ts +0 -2
  114. package/dist/__tests__/useFieldArray/append.test.d.ts.map +0 -1
  115. package/dist/__tests__/useFieldArray/focus.test.d.ts +0 -2
  116. package/dist/__tests__/useFieldArray/focus.test.d.ts.map +0 -1
  117. package/dist/__tests__/useFieldArray/insert.test.d.ts +0 -2
  118. package/dist/__tests__/useFieldArray/insert.test.d.ts.map +0 -1
  119. package/dist/__tests__/useFieldArray/move.test.d.ts +0 -2
  120. package/dist/__tests__/useFieldArray/move.test.d.ts.map +0 -1
  121. package/dist/__tests__/useFieldArray/prepend.test.d.ts +0 -2
  122. package/dist/__tests__/useFieldArray/prepend.test.d.ts.map +0 -1
  123. package/dist/__tests__/useFieldArray/remove.test.d.ts +0 -2
  124. package/dist/__tests__/useFieldArray/remove.test.d.ts.map +0 -1
  125. package/dist/__tests__/useFieldArray/replace.test.d.ts +0 -2
  126. package/dist/__tests__/useFieldArray/replace.test.d.ts.map +0 -1
  127. package/dist/__tests__/useFieldArray/swap.test.d.ts +0 -2
  128. package/dist/__tests__/useFieldArray/swap.test.d.ts.map +0 -1
  129. package/dist/__tests__/useFieldArray/update.test.d.ts +0 -2
  130. package/dist/__tests__/useFieldArray/update.test.d.ts.map +0 -1
  131. package/dist/__tests__/useFieldArray.test.d.ts +0 -2
  132. package/dist/__tests__/useFieldArray.test.d.ts.map +0 -1
  133. package/dist/__tests__/useForm/clearErrors.test.d.ts +0 -2
  134. package/dist/__tests__/useForm/clearErrors.test.d.ts.map +0 -1
  135. package/dist/__tests__/useForm/formState.test.d.ts +0 -2
  136. package/dist/__tests__/useForm/formState.test.d.ts.map +0 -1
  137. package/dist/__tests__/useForm/getFieldState.test.d.ts +0 -2
  138. package/dist/__tests__/useForm/getFieldState.test.d.ts.map +0 -1
  139. package/dist/__tests__/useForm/getValues.test.d.ts +0 -2
  140. package/dist/__tests__/useForm/getValues.test.d.ts.map +0 -1
  141. package/dist/__tests__/useForm/handleSubmit.test.d.ts +0 -2
  142. package/dist/__tests__/useForm/handleSubmit.test.d.ts.map +0 -1
  143. package/dist/__tests__/useForm/register.test.d.ts +0 -2
  144. package/dist/__tests__/useForm/register.test.d.ts.map +0 -1
  145. package/dist/__tests__/useForm/reset.test.d.ts +0 -2
  146. package/dist/__tests__/useForm/reset.test.d.ts.map +0 -1
  147. package/dist/__tests__/useForm/resetField.test.d.ts +0 -2
  148. package/dist/__tests__/useForm/resetField.test.d.ts.map +0 -1
  149. package/dist/__tests__/useForm/resolver.test.d.ts +0 -2
  150. package/dist/__tests__/useForm/resolver.test.d.ts.map +0 -1
  151. package/dist/__tests__/useForm/setError.test.d.ts +0 -2
  152. package/dist/__tests__/useForm/setError.test.d.ts.map +0 -1
  153. package/dist/__tests__/useForm/setFocus.test.d.ts +0 -2
  154. package/dist/__tests__/useForm/setFocus.test.d.ts.map +0 -1
  155. package/dist/__tests__/useForm/setValue.test.d.ts +0 -2
  156. package/dist/__tests__/useForm/setValue.test.d.ts.map +0 -1
  157. package/dist/__tests__/useForm/subscribe.test.d.ts +0 -2
  158. package/dist/__tests__/useForm/subscribe.test.d.ts.map +0 -1
  159. package/dist/__tests__/useForm/trigger.test.d.ts +0 -2
  160. package/dist/__tests__/useForm/trigger.test.d.ts.map +0 -1
  161. package/dist/__tests__/useForm/unregister.test.d.ts +0 -2
  162. package/dist/__tests__/useForm/unregister.test.d.ts.map +0 -1
  163. package/dist/__tests__/useForm/useFormWithNullValues.test.d.ts +0 -2
  164. package/dist/__tests__/useForm/useFormWithNullValues.test.d.ts.map +0 -1
  165. package/dist/__tests__/useForm/watch.test.d.ts +0 -2
  166. package/dist/__tests__/useForm/watch.test.d.ts.map +0 -1
  167. package/dist/__tests__/useForm.server.test.d.ts +0 -2
  168. package/dist/__tests__/useForm.server.test.d.ts.map +0 -1
  169. package/dist/__tests__/useForm.test.d.ts +0 -2
  170. package/dist/__tests__/useForm.test.d.ts.map +0 -1
  171. package/dist/__tests__/useFormContext.server.test.d.ts +0 -2
  172. package/dist/__tests__/useFormContext.server.test.d.ts.map +0 -1
  173. package/dist/__tests__/useFormContext.test.d.ts +0 -2
  174. package/dist/__tests__/useFormContext.test.d.ts.map +0 -1
  175. package/dist/__tests__/useFormState.test.d.ts +0 -2
  176. package/dist/__tests__/useFormState.test.d.ts.map +0 -1
  177. package/dist/__tests__/useWatch.test.d.ts +0 -2
  178. package/dist/__tests__/useWatch.test.d.ts.map +0 -1
  179. package/dist/__tests__/utils/append.test.d.ts +0 -2
  180. package/dist/__tests__/utils/append.test.d.ts.map +0 -1
  181. package/dist/__tests__/utils/cloneObject.test.d.ts +0 -2
  182. package/dist/__tests__/utils/cloneObject.test.d.ts.map +0 -1
  183. package/dist/__tests__/utils/compact.test.d.ts +0 -2
  184. package/dist/__tests__/utils/compact.test.d.ts.map +0 -1
  185. package/dist/__tests__/utils/convertToArrayPayload.test.d.ts +0 -2
  186. package/dist/__tests__/utils/convertToArrayPayload.test.d.ts.map +0 -1
  187. package/dist/__tests__/utils/createSubject.test.d.ts +0 -2
  188. package/dist/__tests__/utils/createSubject.test.d.ts.map +0 -1
  189. package/dist/__tests__/utils/deepEqual.test.d.ts +0 -2
  190. package/dist/__tests__/utils/deepEqual.test.d.ts.map +0 -1
  191. package/dist/__tests__/utils/deepMerge.test.d.ts +0 -2
  192. package/dist/__tests__/utils/deepMerge.test.d.ts.map +0 -1
  193. package/dist/__tests__/utils/extractFormValues.test.d.ts +0 -2
  194. package/dist/__tests__/utils/extractFormValues.test.d.ts.map +0 -1
  195. package/dist/__tests__/utils/fillEmptyArray.test.d.ts +0 -2
  196. package/dist/__tests__/utils/fillEmptyArray.test.d.ts.map +0 -1
  197. package/dist/__tests__/utils/flatten.test.d.ts +0 -2
  198. package/dist/__tests__/utils/flatten.test.d.ts.map +0 -1
  199. package/dist/__tests__/utils/get.test.d.ts +0 -2
  200. package/dist/__tests__/utils/get.test.d.ts.map +0 -1
  201. package/dist/__tests__/utils/insert.test.d.ts +0 -2
  202. package/dist/__tests__/utils/insert.test.d.ts.map +0 -1
  203. package/dist/__tests__/utils/isBoolean.test.d.ts +0 -2
  204. package/dist/__tests__/utils/isBoolean.test.d.ts.map +0 -1
  205. package/dist/__tests__/utils/isCheckBoxInput.test.d.ts +0 -2
  206. package/dist/__tests__/utils/isCheckBoxInput.test.d.ts.map +0 -1
  207. package/dist/__tests__/utils/isEmptyObject.test.d.ts +0 -2
  208. package/dist/__tests__/utils/isEmptyObject.test.d.ts.map +0 -1
  209. package/dist/__tests__/utils/isFileInput.test.d.ts +0 -2
  210. package/dist/__tests__/utils/isFileInput.test.d.ts.map +0 -1
  211. package/dist/__tests__/utils/isFunction.test.d.ts +0 -2
  212. package/dist/__tests__/utils/isFunction.test.d.ts.map +0 -1
  213. package/dist/__tests__/utils/isHTMLElement.test.d.ts +0 -2
  214. package/dist/__tests__/utils/isHTMLElement.test.d.ts.map +0 -1
  215. package/dist/__tests__/utils/isKey.test.d.ts +0 -2
  216. package/dist/__tests__/utils/isKey.test.d.ts.map +0 -1
  217. package/dist/__tests__/utils/isMultipleSelect.test.d.ts +0 -2
  218. package/dist/__tests__/utils/isMultipleSelect.test.d.ts.map +0 -1
  219. package/dist/__tests__/utils/isNullOrUndefined.test.d.ts +0 -2
  220. package/dist/__tests__/utils/isNullOrUndefined.test.d.ts.map +0 -1
  221. package/dist/__tests__/utils/isObject.test.d.ts +0 -2
  222. package/dist/__tests__/utils/isObject.test.d.ts.map +0 -1
  223. package/dist/__tests__/utils/isPrimitive.test.d.ts +0 -2
  224. package/dist/__tests__/utils/isPrimitive.test.d.ts.map +0 -1
  225. package/dist/__tests__/utils/isRadioInput.test.d.ts +0 -2
  226. package/dist/__tests__/utils/isRadioInput.test.d.ts.map +0 -1
  227. package/dist/__tests__/utils/isRadioOrCheckbox.test.d.ts +0 -2
  228. package/dist/__tests__/utils/isRadioOrCheckbox.test.d.ts.map +0 -1
  229. package/dist/__tests__/utils/isRegex.test.d.ts +0 -2
  230. package/dist/__tests__/utils/isRegex.test.d.ts.map +0 -1
  231. package/dist/__tests__/utils/isString.test.d.ts +0 -2
  232. package/dist/__tests__/utils/isString.test.d.ts.map +0 -1
  233. package/dist/__tests__/utils/isUndefined.test.d.ts +0 -2
  234. package/dist/__tests__/utils/isUndefined.test.d.ts.map +0 -1
  235. package/dist/__tests__/utils/live.test.d.ts +0 -2
  236. package/dist/__tests__/utils/live.test.d.ts.map +0 -1
  237. package/dist/__tests__/utils/move.test.d.ts +0 -2
  238. package/dist/__tests__/utils/move.test.d.ts.map +0 -1
  239. package/dist/__tests__/utils/noop.test.d.ts +0 -2
  240. package/dist/__tests__/utils/noop.test.d.ts.map +0 -1
  241. package/dist/__tests__/utils/objectHasFunction.test.d.ts +0 -2
  242. package/dist/__tests__/utils/objectHasFunction.test.d.ts.map +0 -1
  243. package/dist/__tests__/utils/prepend.test.d.ts +0 -2
  244. package/dist/__tests__/utils/prepend.test.d.ts.map +0 -1
  245. package/dist/__tests__/utils/remove.test.d.ts +0 -2
  246. package/dist/__tests__/utils/remove.test.d.ts.map +0 -1
  247. package/dist/__tests__/utils/set.test.d.ts +0 -2
  248. package/dist/__tests__/utils/set.test.d.ts.map +0 -1
  249. package/dist/__tests__/utils/stringToPath.test.d.ts +0 -2
  250. package/dist/__tests__/utils/stringToPath.test.d.ts.map +0 -1
  251. package/dist/__tests__/utils/swap.test.d.ts +0 -2
  252. package/dist/__tests__/utils/swap.test.d.ts.map +0 -1
  253. package/dist/__tests__/utils/unset.test.d.ts +0 -2
  254. package/dist/__tests__/utils/unset.test.d.ts.map +0 -1
  255. package/dist/__tests__/utils/validationModeChecker.test.d.ts +0 -2
  256. package/dist/__tests__/utils/validationModeChecker.test.d.ts.map +0 -1
  257. package/dist/__tests__/watch.server.test.d.ts +0 -2
  258. package/dist/__tests__/watch.server.test.d.ts.map +0 -1
  259. package/dist/__tests__/watch.test.d.ts +0 -2
  260. package/dist/__tests__/watch.test.d.ts.map +0 -1
  261. package/dist/logic/isNameInFieldArray.d.ts.map +0 -1
@@ -18,9 +18,15 @@ var getEventValue = (event) => isObject(event) && event.target
18
18
  : event.target.value
19
19
  : event;
20
20
 
21
- var getNodeParentName = (name) => name.substring(0, name.search(/\.\d+(\.|$)/)) || name;
22
-
23
- var isNameInFieldArray = (names, name) => names.has(getNodeParentName(name));
21
+ var getFieldArrayParentNames = (names, name) => {
22
+ const parts = name.split('.');
23
+ const matches = [];
24
+ let prefix = parts[0];
25
+ for (let i = 1; i < parts.length; prefix += '.' + parts[i++]) {
26
+ !isNaN(+parts[i]) && names.has(prefix) && matches.push(prefix);
27
+ }
28
+ return matches;
29
+ };
24
30
 
25
31
  var isPlainObject = (tempObject) => {
26
32
  const prototypeCopy = tempObject.constructor && tempObject.constructor.prototype;
@@ -64,7 +70,10 @@ var get = (object, path, defaultValue) => {
64
70
  if (!path || !isObject(object)) {
65
71
  return defaultValue;
66
72
  }
67
- const result = (isKey(path) ? [path] : stringToPath(path)).reduce((result, key) => isNullOrUndefined(result) ? result : result[key], object);
73
+ const paths = isKey(path) ? [path] : stringToPath(path);
74
+ const result = paths.reduce((result, key) => {
75
+ return isNullOrUndefined(result) ? undefined : result[key];
76
+ }, object);
68
77
  return isUndefined(result) || result === object
69
78
  ? isUndefined(object[path])
70
79
  ? defaultValue
@@ -103,6 +112,9 @@ const EVENTS = {
103
112
  BLUR: 'blur',
104
113
  FOCUS_OUT: 'focusout',
105
114
  CHANGE: 'change',
115
+ SUBMIT: 'submit',
116
+ TRIGGER: 'trigger',
117
+ VALID: 'valid',
106
118
  };
107
119
  const VALIDATION_MODE = {
108
120
  onBlur: 'onBlur',
@@ -120,6 +132,8 @@ const INPUT_VALIDATION_RULES = {
120
132
  required: 'required',
121
133
  validate: 'validate',
122
134
  };
135
+ const FORM_ERROR_TYPE = 'form';
136
+ const ROOT_ERROR_TYPE = 'root';
123
137
 
124
138
  /**
125
139
  * Separate context for `control` to prevent unnecessary rerenders.
@@ -133,10 +147,7 @@ HookFormControlContext.displayName = 'HookFormControlContext';
133
147
  const useFormControlContext = () => React.useContext(HookFormControlContext);
134
148
 
135
149
  var getProxyFormState = (formState, control, localProxyFormState, isRoot = true) => {
136
- const result = {
137
- ...formState,
138
- defaultValues: control._defaultValues,
139
- };
150
+ const result = {};
140
151
  for (const key in formState) {
141
152
  Object.defineProperty(result, key, {
142
153
  get: () => {
@@ -187,7 +198,10 @@ const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? React.useLayou
187
198
  function useFormState(props) {
188
199
  const formControl = useFormControlContext();
189
200
  const { control = formControl, disabled, name, exact } = props || {};
190
- const [formState, updateFormState] = React.useState(control._formState);
201
+ const [formState, updateFormState] = React.useState(() => ({
202
+ ...control._formState,
203
+ defaultValues: control._defaultValues,
204
+ }));
191
205
  const _localProxyFormState = React.useRef({
192
206
  isDirty: false,
193
207
  isLoading: false,
@@ -207,6 +221,7 @@ function useFormState(props) {
207
221
  updateFormState({
208
222
  ...control._formState,
209
223
  ...formState,
224
+ defaultValues: control._defaultValues,
210
225
  });
211
226
  },
212
227
  }), [name, disabled, exact]);
@@ -233,7 +248,10 @@ var generateWatchOutput = (names, _names, formValues, isGlobal, defaultValue) =>
233
248
 
234
249
  var isPrimitive = (value) => isNullOrUndefined(value) || !isObjectType(value);
235
250
 
236
- function deepEqual(object1, object2, _internal_visited = new WeakSet()) {
251
+ function deepEqual(object1, object2, visited = new WeakSet()) {
252
+ if (object1 === object2) {
253
+ return true;
254
+ }
237
255
  if (isPrimitive(object1) || isPrimitive(object2)) {
238
256
  return Object.is(object1, object2);
239
257
  }
@@ -245,22 +263,22 @@ function deepEqual(object1, object2, _internal_visited = new WeakSet()) {
245
263
  if (keys1.length !== keys2.length) {
246
264
  return false;
247
265
  }
248
- if (_internal_visited.has(object1) || _internal_visited.has(object2)) {
266
+ if (visited.has(object1) || visited.has(object2)) {
249
267
  return true;
250
268
  }
251
- _internal_visited.add(object1);
252
- _internal_visited.add(object2);
269
+ visited.add(object1);
270
+ visited.add(object2);
253
271
  for (const key of keys1) {
254
272
  const val1 = object1[key];
255
- if (!keys2.includes(key)) {
273
+ if (!(key in object2)) {
256
274
  return false;
257
275
  }
258
276
  if (key !== 'ref') {
259
277
  const val2 = object2[key];
260
278
  if ((isDateObject(val1) && isDateObject(val2)) ||
261
- (isObject(val1) && isObject(val2)) ||
262
- (Array.isArray(val1) && Array.isArray(val2))
263
- ? !deepEqual(val1, val2, _internal_visited)
279
+ ((isObject(val1) || Array.isArray(val1)) &&
280
+ (isObject(val2) || Array.isArray(val2)))
281
+ ? !deepEqual(val1, val2, visited)
264
282
  : !Object.is(val1, val2)) {
265
283
  return false;
266
284
  }
@@ -382,7 +400,8 @@ function useWatch(props) {
382
400
  function useController(props) {
383
401
  const formControl = useFormControlContext();
384
402
  const { name, disabled, control = formControl, shouldUnregister, defaultValue, exact = true, } = props;
385
- const isArrayField = isNameInFieldArray(control._names.array, name);
403
+ const isArrayField = !!getFieldArrayParentNames(control._names.array, name)
404
+ .length;
386
405
  const defaultValueMemo = React.useMemo(() => get(control._formValues, name, get(control._defaultValues, name, defaultValue)), [control, name, defaultValue]);
387
406
  const value = useWatch({
388
407
  control,
@@ -396,7 +415,6 @@ function useController(props) {
396
415
  exact,
397
416
  });
398
417
  const _props = React.useRef(props);
399
- const _previousNameRef = React.useRef(undefined);
400
418
  const _registerProps = React.useRef(control.register(name, {
401
419
  ...props.rules,
402
420
  value,
@@ -457,10 +475,6 @@ function useController(props) {
457
475
  }), [name, disabled, formState.disabled, onChange, onBlur, ref, value]);
458
476
  React.useEffect(() => {
459
477
  const _shouldUnregisterField = control._options.shouldUnregister || shouldUnregister;
460
- const previousName = _previousNameRef.current;
461
- if (previousName && previousName !== name && !isArrayField) {
462
- control.unregister(previousName);
463
- }
464
478
  control.register(name, {
465
479
  ..._props.current.rules,
466
480
  ...(isBoolean(_props.current.disabled)
@@ -475,14 +489,13 @@ function useController(props) {
475
489
  };
476
490
  updateMounted(name, true);
477
491
  if (_shouldUnregisterField) {
478
- const value = cloneObject(get(control._options.defaultValues, name, _props.current.defaultValue));
492
+ const value = cloneObject(get(control._defaultValues, name, get(control._options.defaultValues, name, _props.current.defaultValue)));
479
493
  set(control._defaultValues, name, value);
480
494
  if (isUndefined(get(control._formValues, name))) {
481
495
  set(control._formValues, name, value);
482
496
  }
483
497
  }
484
498
  !isArrayField && control.register(name);
485
- _previousNameRef.current = name;
486
499
  return () => {
487
500
  (isArrayField
488
501
  ? _shouldUnregisterField && !control._state.action
@@ -628,43 +641,46 @@ const useFormContext = () => React.useContext(HookFormContext);
628
641
  * ```
629
642
  */
630
643
  const FormProvider = (props) => {
631
- const { children, watch, getValues, getFieldState, setError, clearErrors, setValue, trigger, formState, resetField, reset, handleSubmit, unregister, control, register, setFocus, subscribe, } = props;
632
- return (React.createElement(HookFormContext.Provider, { value: React.useMemo(() => ({
633
- watch,
634
- getValues,
635
- getFieldState,
636
- setError,
637
- clearErrors,
638
- setValue,
639
- trigger,
640
- formState,
641
- resetField,
642
- reset,
643
- handleSubmit,
644
- unregister,
645
- control,
646
- register,
647
- setFocus,
648
- subscribe,
649
- }), [
650
- clearErrors,
651
- control,
652
- formState,
653
- getFieldState,
654
- getValues,
655
- handleSubmit,
656
- register,
657
- reset,
658
- resetField,
659
- setError,
660
- setFocus,
661
- setValue,
662
- subscribe,
663
- trigger,
664
- unregister,
665
- watch,
666
- ]) },
667
- React.createElement(HookFormControlContext.Provider, { value: control }, children)));
644
+ const { children, watch, getValues, getFieldState, setError, clearErrors, setValue, setValues, trigger, formState, resetField, reset, handleSubmit, unregister, control, register, setFocus, subscribe, } = props;
645
+ const memoizedValue = React.useMemo(() => ({
646
+ watch,
647
+ getValues,
648
+ getFieldState,
649
+ setError,
650
+ clearErrors,
651
+ setValue,
652
+ setValues,
653
+ trigger,
654
+ formState,
655
+ resetField,
656
+ reset,
657
+ handleSubmit,
658
+ unregister,
659
+ control,
660
+ register,
661
+ setFocus,
662
+ subscribe,
663
+ }), [
664
+ clearErrors,
665
+ control,
666
+ formState,
667
+ getFieldState,
668
+ getValues,
669
+ handleSubmit,
670
+ register,
671
+ reset,
672
+ resetField,
673
+ setError,
674
+ setFocus,
675
+ setValue,
676
+ setValues,
677
+ subscribe,
678
+ trigger,
679
+ unregister,
680
+ watch,
681
+ ]);
682
+ return (React.createElement(HookFormContext.Provider, { value: memoizedValue },
683
+ React.createElement(HookFormControlContext.Provider, { value: memoizedValue.control }, children)));
668
684
  };
669
685
 
670
686
  const POST_REQUEST = 'post';
@@ -694,7 +710,7 @@ function Form(props) {
694
710
  const methods = useFormContext();
695
711
  const [mounted, setMounted] = React.useState(false);
696
712
  const { control = methods.control, onSubmit, children, action, method = POST_REQUEST, headers, encType, onError, render, onSuccess, validateStatus, ...rest } = props;
697
- const submit = async (event) => {
713
+ const submit = React.useCallback(async (event) => {
698
714
  let hasError = false;
699
715
  let type = '';
700
716
  await control.handleSubmit(async (data) => {
@@ -703,8 +719,8 @@ function Form(props) {
703
719
  try {
704
720
  formDataJson = JSON.stringify(data);
705
721
  }
706
- catch (_a) { }
707
- const flattenFormValues = flatten(control._formValues);
722
+ catch { }
723
+ const flattenFormValues = flatten(data);
708
724
  for (const key in flattenFormValues) {
709
725
  formData.append(key, flattenFormValues[key]);
710
726
  }
@@ -751,15 +767,25 @@ function Form(props) {
751
767
  }
752
768
  }
753
769
  })(event);
754
- if (hasError && props.control) {
755
- props.control._subjects.state.next({
770
+ if (hasError && control) {
771
+ control._subjects.state.next({
756
772
  isSubmitSuccessful: false,
757
773
  });
758
- props.control.setError('root.server', {
774
+ control.setError('root.server', {
759
775
  type,
760
776
  });
761
777
  }
762
- };
778
+ }, [
779
+ control,
780
+ onSubmit,
781
+ method,
782
+ action,
783
+ headers,
784
+ encType,
785
+ validateStatus,
786
+ onError,
787
+ onSuccess,
788
+ ]);
763
789
  React.useEffect(() => {
764
790
  setMounted(true);
765
791
  }, []);
@@ -857,7 +883,12 @@ function baseGet(object, updatePath) {
857
883
  const length = updatePath.slice(0, -1).length;
858
884
  let index = 0;
859
885
  while (index < length) {
860
- object = isUndefined(object) ? index++ : object[updatePath[index++]];
886
+ if (isNullOrUndefined(object)) {
887
+ object = undefined;
888
+ break;
889
+ }
890
+ object = object[updatePath[index]];
891
+ index++;
861
892
  }
862
893
  return object;
863
894
  }
@@ -870,6 +901,10 @@ function isEmptyArray(obj) {
870
901
  return true;
871
902
  }
872
903
  function unset(object, path) {
904
+ if (isString(path) && Object.prototype.hasOwnProperty.call(object, path)) {
905
+ delete object[path];
906
+ return object;
907
+ }
873
908
  const paths = Array.isArray(path)
874
909
  ? path
875
910
  : isKey(path)
@@ -914,6 +949,29 @@ function markFieldsDirty(data, fields = {}) {
914
949
  }
915
950
  return fields;
916
951
  }
952
+ function pruneDirtyFields(value) {
953
+ if (value === false) {
954
+ return undefined;
955
+ }
956
+ if (value === true) {
957
+ return true;
958
+ }
959
+ if (Array.isArray(value)) {
960
+ const result = value.map((value) => pruneDirtyFields(value));
961
+ return (result.some((value) => value !== undefined) ? result : undefined);
962
+ }
963
+ if (isObject(value)) {
964
+ const result = {};
965
+ for (const key in value) {
966
+ const pruned = pruneDirtyFields(value[key]);
967
+ if (!isUndefined(pruned)) {
968
+ result[key] = pruned;
969
+ }
970
+ }
971
+ return (Object.keys(result).length ? result : undefined);
972
+ }
973
+ return undefined;
974
+ }
917
975
  function getDirtyFields(data, formValues, dirtyFieldsFromValues) {
918
976
  if (!dirtyFieldsFromValues) {
919
977
  dirtyFieldsFromValues = markFieldsDirty(formValues);
@@ -933,7 +991,7 @@ function getDirtyFields(data, formValues, dirtyFieldsFromValues) {
933
991
  dirtyFieldsFromValues[key] = !deepEqual(value, formValue);
934
992
  }
935
993
  }
936
- return dirtyFieldsFromValues;
994
+ return pruneDirtyFields(dirtyFieldsFromValues) || {};
937
995
  }
938
996
 
939
997
  const defaultResult = {
@@ -1129,7 +1187,8 @@ var shouldRenderFormState = (formStateData, _proxyFormState, updateFormState, is
1129
1187
  updateFormState(formStateData);
1130
1188
  const { name, ...formState } = formStateData;
1131
1189
  return (isEmptyObject(formState) ||
1132
- Object.keys(formState).length >= Object.keys(_proxyFormState).length ||
1190
+ (isRoot &&
1191
+ Object.keys(formState).length >= Object.keys(_proxyFormState).length) ||
1133
1192
  Object.keys(formState).find((key) => _proxyFormState[key] ===
1134
1193
  (!isRoot || VALIDATION_MODE.all)));
1135
1194
  };
@@ -1163,7 +1222,7 @@ var unsetEmptyArray = (ref, name) => !compact(get(ref, name)).length && unset(re
1163
1222
 
1164
1223
  var updateFieldArrayRootError = (errors, error, name) => {
1165
1224
  const fieldArrayErrors = convertToArrayPayload(get(errors, name));
1166
- set(fieldArrayErrors, 'root', error[name]);
1225
+ set(fieldArrayErrors, ROOT_ERROR_TYPE, error[name]);
1167
1226
  set(errors, name, fieldArrayErrors);
1168
1227
  return errors;
1169
1228
  };
@@ -1209,7 +1268,8 @@ var validateField = async (field, disabledFieldNames, formValues, validateAllFie
1209
1268
  isUndefined(inputValue)) ||
1210
1269
  (isHTMLElement(ref) && ref.value === '') ||
1211
1270
  inputValue === '' ||
1212
- (Array.isArray(inputValue) && !inputValue.length);
1271
+ (Array.isArray(inputValue) && !inputValue.length) ||
1272
+ (valueAsNumber && typeof inputValue === 'number' && isNaN(inputValue));
1213
1273
  const appendErrorsCurry = appendErrors.bind(null, name, validateAllFieldCriteria, error);
1214
1274
  const getMinMaxMessage = (exceedMax, maxLengthMessage, minLengthMessage, maxType = INPUT_VALIDATION_RULES.maxLength, minType = INPUT_VALIDATION_RULES.minLength) => {
1215
1275
  const message = exceedMax ? maxLengthMessage : minLengthMessage;
@@ -1371,24 +1431,27 @@ const defaultOptions = {
1371
1431
  reValidateMode: VALIDATION_MODE.onChange,
1372
1432
  shouldFocusError: true,
1373
1433
  };
1434
+ const DEFAULT_FORM_STATE = {
1435
+ submitCount: 0,
1436
+ isDirty: false,
1437
+ isReady: false,
1438
+ isValidating: false,
1439
+ isSubmitted: false,
1440
+ isSubmitting: false,
1441
+ isSubmitSuccessful: false,
1442
+ isValid: false,
1443
+ touchedFields: {},
1444
+ dirtyFields: {},
1445
+ validatingFields: {},
1446
+ };
1374
1447
  function createFormControl(props = {}) {
1375
1448
  let _options = {
1376
1449
  ...defaultOptions,
1377
1450
  ...props,
1378
1451
  };
1379
1452
  let _formState = {
1380
- submitCount: 0,
1381
- isDirty: false,
1382
- isReady: false,
1453
+ ...cloneObject(DEFAULT_FORM_STATE),
1383
1454
  isLoading: isFunction(_options.defaultValues),
1384
- isValidating: false,
1385
- isSubmitted: false,
1386
- isSubmitting: false,
1387
- isSubmitSuccessful: false,
1388
- isValid: false,
1389
- touchedFields: {},
1390
- dirtyFields: {},
1391
- validatingFields: {},
1392
1455
  errors: _options.errors || {},
1393
1456
  disabled: _options.disabled || false,
1394
1457
  };
@@ -1411,6 +1474,7 @@ function createFormControl(props = {}) {
1411
1474
  unMount: new Set(),
1412
1475
  array: new Set(),
1413
1476
  watch: new Set(),
1477
+ registerName: new Set(),
1414
1478
  };
1415
1479
  let delayErrorCallback;
1416
1480
  let timer = 0;
@@ -1452,7 +1516,11 @@ function createFormControl(props = {}) {
1452
1516
  _updateIsValidating();
1453
1517
  }
1454
1518
  else {
1455
- isValid = await executeBuiltInValidation(_fields, true);
1519
+ isValid = await executeBuiltInValidation({
1520
+ fields: _fields,
1521
+ onlyCheckValid: true,
1522
+ eventType: EVENTS.VALID,
1523
+ });
1456
1524
  }
1457
1525
  if (isValid !== _formState.isValid) {
1458
1526
  _subjects.state.next({
@@ -1480,6 +1548,9 @@ function createFormControl(props = {}) {
1480
1548
  });
1481
1549
  }
1482
1550
  };
1551
+ const _updateDirtyFields = () => {
1552
+ _formState.dirtyFields = getDirtyFields(_defaultValues, _formValues);
1553
+ };
1483
1554
  const _setFieldArray = (name, values = [], method, args, shouldSetValues = true, shouldUpdateFieldsAndState = true) => {
1484
1555
  if (args && method && !_options.disabled) {
1485
1556
  _state.action = true;
@@ -1501,7 +1572,7 @@ function createFormControl(props = {}) {
1501
1572
  shouldSetValues && set(_formState.touchedFields, name, touchedFields);
1502
1573
  }
1503
1574
  if (_proxyFormState.dirtyFields || _proxySubscribeFormState.dirtyFields) {
1504
- _formState.dirtyFields = getDirtyFields(_defaultValues, _formValues);
1575
+ _updateDirtyFields();
1505
1576
  }
1506
1577
  _subjects.state.next({
1507
1578
  name,
@@ -1528,16 +1599,53 @@ function createFormControl(props = {}) {
1528
1599
  isValid: false,
1529
1600
  });
1530
1601
  };
1602
+ const hasExplicitNullIntermediate = (name) => {
1603
+ const segments = isKey(name) ? [name] : stringToPath(name);
1604
+ let formValues = _formValues;
1605
+ let defaultValues = _defaultValues;
1606
+ for (let i = 0; i < segments.length - 1; i++) {
1607
+ const key = segments[i];
1608
+ formValues = isNullOrUndefined(formValues) ? formValues : formValues[key];
1609
+ defaultValues = isNullOrUndefined(defaultValues)
1610
+ ? defaultValues
1611
+ : defaultValues[key];
1612
+ if (formValues === null && defaultValues !== null) {
1613
+ return true;
1614
+ }
1615
+ }
1616
+ return false;
1617
+ };
1531
1618
  const updateValidAndValue = (name, shouldSkipSetValueAs, value, ref) => {
1532
1619
  const field = get(_fields, name);
1533
1620
  if (field) {
1621
+ if (hasExplicitNullIntermediate(name)) {
1622
+ return;
1623
+ }
1624
+ const wasUnsetInFormValues = isUndefined(get(_formValues, name));
1534
1625
  const defaultValue = get(_formValues, name, isUndefined(value) ? get(_defaultValues, name) : value);
1535
1626
  isUndefined(defaultValue) ||
1536
1627
  (ref && ref.defaultChecked) ||
1537
1628
  shouldSkipSetValueAs
1538
1629
  ? set(_formValues, name, shouldSkipSetValueAs ? defaultValue : getFieldValue(field._f))
1539
1630
  : setFieldValue(name, defaultValue);
1540
- _state.mount && !_state.action && _setValid();
1631
+ if (_state.mount && !_state.action) {
1632
+ _setValid();
1633
+ // Re-registering a field after a prior unregister puts its key back
1634
+ // into _formValues, which can flip isDirty back to false (#13397).
1635
+ // Only run when we are currently dirty, otherwise an initial register
1636
+ // for a field with no defaultValue would flip isDirty to true. Reset
1637
+ // paths repopulate _formValues before re-register, so the key is
1638
+ // present then and this branch is skipped (preserves keepDirty).
1639
+ if (wasUnsetInFormValues &&
1640
+ _formState.isDirty &&
1641
+ (_proxyFormState.isDirty || _proxySubscribeFormState.isDirty)) {
1642
+ const isDirty = _getDirty();
1643
+ if (!isDirty) {
1644
+ _formState.isDirty = false;
1645
+ _subjects.state.next({ ..._formState });
1646
+ }
1647
+ }
1648
+ }
1541
1649
  }
1542
1650
  };
1543
1651
  const updateTouchAndDirty = (name, fieldValue, isBlurEvent, shouldDirty, shouldRender) => {
@@ -1555,9 +1663,14 @@ function createFormControl(props = {}) {
1555
1663
  }
1556
1664
  const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
1557
1665
  isPreviousDirty = !!get(_formState.dirtyFields, name);
1558
- isCurrentFieldPristine
1559
- ? unset(_formState.dirtyFields, name)
1560
- : set(_formState.dirtyFields, name, true);
1666
+ if (isCurrentFieldPristine !== _formState.isDirty) {
1667
+ _formState.dirtyFields = getDirtyFields(_defaultValues, _formValues);
1668
+ }
1669
+ else {
1670
+ isCurrentFieldPristine
1671
+ ? unset(_formState.dirtyFields, name)
1672
+ : set(_formState.dirtyFields, name, true);
1673
+ }
1561
1674
  output.dirtyFields = _formState.dirtyFields;
1562
1675
  shouldUpdateField =
1563
1676
  shouldUpdateField ||
@@ -1615,8 +1728,7 @@ function createFormControl(props = {}) {
1615
1728
  };
1616
1729
  const _runSchema = async (name) => {
1617
1730
  _updateIsValidating(name, true);
1618
- const result = await _options.resolver(_formValues, _options.context, getResolverOptions(name || _names.mount, _fields, _options.criteriaMode, _options.shouldUseNativeValidation));
1619
- return result;
1731
+ return await _options.resolver(_formValues, _options.context, getResolverOptions(name || _names.mount, _fields, _options.criteriaMode, _options.shouldUseNativeValidation));
1620
1732
  };
1621
1733
  const executeSchemaAndUpdateState = async (names) => {
1622
1734
  const { errors } = await _runSchema(names);
@@ -1625,7 +1737,9 @@ function createFormControl(props = {}) {
1625
1737
  for (const name of names) {
1626
1738
  const error = get(errors, name);
1627
1739
  error
1628
- ? set(_formState.errors, name, error)
1740
+ ? _names.array.has(name) && isObject(error)
1741
+ ? updateFieldArrayRootError(_formState.errors, { [name]: error }, name)
1742
+ : set(_formState.errors, name, error)
1629
1743
  : unset(_formState.errors, name);
1630
1744
  }
1631
1745
  }
@@ -1634,9 +1748,55 @@ function createFormControl(props = {}) {
1634
1748
  }
1635
1749
  return errors;
1636
1750
  };
1637
- const executeBuiltInValidation = async (fields, shouldOnlyCheckValid, context = {
1751
+ const validateForm = async ({ name, eventType, }) => {
1752
+ if (props.validate) {
1753
+ const result = await props.validate({
1754
+ formValues: _formValues,
1755
+ formState: _formState,
1756
+ name,
1757
+ eventType,
1758
+ });
1759
+ if (isObject(result)) {
1760
+ for (const key in result) {
1761
+ const error = result[key];
1762
+ if (error) {
1763
+ setError(`${FORM_ERROR_TYPE}.${key}`, {
1764
+ message: isString(error.message) ? error.message : '',
1765
+ type: error.type || INPUT_VALIDATION_RULES.validate,
1766
+ });
1767
+ }
1768
+ }
1769
+ }
1770
+ else if (isString(result) || !result) {
1771
+ setError(FORM_ERROR_TYPE, {
1772
+ message: result || '',
1773
+ type: INPUT_VALIDATION_RULES.validate,
1774
+ });
1775
+ }
1776
+ else {
1777
+ clearErrors(FORM_ERROR_TYPE);
1778
+ }
1779
+ return result;
1780
+ }
1781
+ return true;
1782
+ };
1783
+ const executeBuiltInValidation = async ({ fields, onlyCheckValid, name, eventType, context = {
1638
1784
  valid: true,
1639
- }) => {
1785
+ runRootValidation: false,
1786
+ }, }) => {
1787
+ if (props.validate) {
1788
+ context.runRootValidation = true;
1789
+ const result = await validateForm({
1790
+ name,
1791
+ eventType,
1792
+ });
1793
+ if (!result) {
1794
+ context.valid = false;
1795
+ if (onlyCheckValid) {
1796
+ return context.valid;
1797
+ }
1798
+ }
1799
+ }
1640
1800
  for (const name in fields) {
1641
1801
  const field = fields[name];
1642
1802
  if (field) {
@@ -1644,28 +1804,41 @@ function createFormControl(props = {}) {
1644
1804
  if (_f) {
1645
1805
  const isFieldArrayRoot = _names.array.has(_f.name);
1646
1806
  const isPromiseFunction = field._f && hasPromiseValidation(field._f);
1647
- if (isPromiseFunction && _proxyFormState.validatingFields) {
1807
+ const shouldTrackIsValidatingState = _proxyFormState.validatingFields ||
1808
+ _proxyFormState.isValidating ||
1809
+ _proxySubscribeFormState.validatingFields ||
1810
+ _proxySubscribeFormState.isValidating;
1811
+ if (isPromiseFunction && shouldTrackIsValidatingState) {
1648
1812
  _updateIsValidating([_f.name], true);
1649
1813
  }
1650
- const fieldError = await validateField(field, _names.disabled, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation && !shouldOnlyCheckValid, isFieldArrayRoot);
1651
- if (isPromiseFunction && _proxyFormState.validatingFields) {
1814
+ const fieldError = await validateField(field, _names.disabled, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation && !onlyCheckValid, isFieldArrayRoot);
1815
+ if (isPromiseFunction && shouldTrackIsValidatingState) {
1652
1816
  _updateIsValidating([_f.name]);
1653
1817
  }
1654
1818
  if (fieldError[_f.name]) {
1655
1819
  context.valid = false;
1656
- if (shouldOnlyCheckValid || props.shouldUseNativeValidation) {
1820
+ if (onlyCheckValid) {
1657
1821
  break;
1658
1822
  }
1659
1823
  }
1660
- !shouldOnlyCheckValid &&
1824
+ !onlyCheckValid &&
1661
1825
  (get(fieldError, _f.name)
1662
1826
  ? isFieldArrayRoot
1663
1827
  ? updateFieldArrayRootError(_formState.errors, fieldError, _f.name)
1664
1828
  : set(_formState.errors, _f.name, fieldError[_f.name])
1665
1829
  : unset(_formState.errors, _f.name));
1830
+ if (props.shouldUseNativeValidation && fieldError[_f.name]) {
1831
+ break;
1832
+ }
1666
1833
  }
1667
1834
  !isEmptyObject(fieldValue) &&
1668
- (await executeBuiltInValidation(fieldValue, shouldOnlyCheckValid, context));
1835
+ (await executeBuiltInValidation({
1836
+ context,
1837
+ onlyCheckValid,
1838
+ fields: fieldValue,
1839
+ name: name,
1840
+ eventType,
1841
+ }));
1669
1842
  }
1670
1843
  }
1671
1844
  return context.valid;
@@ -1745,7 +1918,7 @@ function createFormControl(props = {}) {
1745
1918
  updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty, true);
1746
1919
  options.shouldValidate && trigger(name);
1747
1920
  };
1748
- const setValues = (name, value, options) => {
1921
+ const setFieldValues = (name, value, options) => {
1749
1922
  for (const fieldKey in value) {
1750
1923
  if (!value.hasOwnProperty(fieldKey)) {
1751
1924
  return;
@@ -1757,7 +1930,7 @@ function createFormControl(props = {}) {
1757
1930
  isObject(fieldValue) ||
1758
1931
  (field && !field._f)) &&
1759
1932
  !isDateObject(fieldValue)
1760
- ? setValues(fieldName, fieldValue, options)
1933
+ ? setFieldValues(fieldName, fieldValue, options)
1761
1934
  : setFieldValue(fieldName, fieldValue, options);
1762
1935
  }
1763
1936
  };
@@ -1765,7 +1938,11 @@ function createFormControl(props = {}) {
1765
1938
  const field = get(_fields, name);
1766
1939
  const isFieldArray = _names.array.has(name);
1767
1940
  const cloneValue = cloneObject(value);
1768
- set(_formValues, name, cloneValue);
1941
+ const previousValue = get(_formValues, name);
1942
+ const isValueUnchanged = deepEqual(previousValue, cloneValue);
1943
+ if (!isValueUnchanged) {
1944
+ set(_formValues, name, cloneValue);
1945
+ }
1769
1946
  if (isFieldArray) {
1770
1947
  _subjects.array.next({
1771
1948
  name,
@@ -1776,30 +1953,52 @@ function createFormControl(props = {}) {
1776
1953
  _proxySubscribeFormState.isDirty ||
1777
1954
  _proxySubscribeFormState.dirtyFields) &&
1778
1955
  options.shouldDirty) {
1956
+ _updateDirtyFields();
1779
1957
  _subjects.state.next({
1780
1958
  name,
1781
- dirtyFields: getDirtyFields(_defaultValues, _formValues),
1959
+ dirtyFields: _formState.dirtyFields,
1782
1960
  isDirty: _getDirty(name, cloneValue),
1783
1961
  });
1784
1962
  }
1785
1963
  }
1786
1964
  else {
1787
- field && !field._f && !isNullOrUndefined(cloneValue)
1788
- ? setValues(name, cloneValue, options)
1789
- : setFieldValue(name, cloneValue, options);
1965
+ const isEmpty = (Array.isArray(cloneValue) && !cloneValue.length) ||
1966
+ isEmptyObject(cloneValue);
1967
+ if (!field || field._f || isNullOrUndefined(cloneValue) || isEmpty) {
1968
+ setFieldValue(name, cloneValue, options);
1969
+ }
1970
+ else {
1971
+ setFieldValues(name, cloneValue, options);
1972
+ }
1790
1973
  }
1791
- if (isWatched(name, _names)) {
1974
+ if (!isValueUnchanged) {
1975
+ const watched = isWatched(name, _names);
1976
+ const values = cloneObject(_formValues);
1977
+ if (!isFieldArray) {
1978
+ for (const arrayName of getFieldArrayParentNames(_names.array, name)) {
1979
+ _subjects.array.next({ name: arrayName, values });
1980
+ }
1981
+ }
1792
1982
  _subjects.state.next({
1793
- ..._formState,
1794
- name,
1795
- values: cloneObject(_formValues),
1983
+ ...(watched && _formState),
1984
+ name: _state.mount || watched ? name : undefined,
1985
+ values,
1796
1986
  });
1797
1987
  }
1798
- else {
1799
- _subjects.state.next({
1800
- name: _state.mount ? name : undefined,
1801
- values: cloneObject(_formValues),
1802
- });
1988
+ };
1989
+ const setValues = (formValues) => {
1990
+ const updatedFormValues = isFunction(formValues)
1991
+ ? formValues(_formValues)
1992
+ : formValues;
1993
+ if (!deepEqual(_formValues, updatedFormValues)) {
1994
+ _formValues = {
1995
+ ..._formValues,
1996
+ ...updatedFormValues,
1997
+ };
1998
+ for (const fieldName of _names.mount) {
1999
+ setValue(fieldName, get(updatedFormValues, fieldName));
2000
+ }
2001
+ _subjects.state.next({ ..._formState, values: _formValues });
1803
2002
  }
1804
2003
  };
1805
2004
  const onChange = async (event) => {
@@ -1824,6 +2023,7 @@ function createFormControl(props = {}) {
1824
2023
  : getEventValue(event);
1825
2024
  const isBlurEvent = event.type === EVENTS.BLUR || event.type === EVENTS.FOCUS_OUT;
1826
2025
  const shouldSkipValidation = (!hasValidation(field._f) &&
2026
+ !props.validate &&
1827
2027
  !_options.resolver &&
1828
2028
  !get(_formState.errors, name) &&
1829
2029
  !field._f.deps) ||
@@ -1861,6 +2061,12 @@ function createFormControl(props = {}) {
1861
2061
  return (shouldRender &&
1862
2062
  _subjects.state.next({ name, ...(watched ? {} : fieldState) }));
1863
2063
  }
2064
+ if (!_options.resolver && props.validate) {
2065
+ await validateForm({
2066
+ name: name,
2067
+ eventType: event.type,
2068
+ });
2069
+ }
1864
2070
  !isBlurEvent && watched && _subjects.state.next({ ..._formState });
1865
2071
  if (_options.resolver) {
1866
2072
  const { errors } = await _runSchema([name]);
@@ -1885,7 +2091,12 @@ function createFormControl(props = {}) {
1885
2091
  }
1886
2092
  else if (_proxyFormState.isValid ||
1887
2093
  _proxySubscribeFormState.isValid) {
1888
- isValid = await executeBuiltInValidation(_fields, true);
2094
+ isValid = await executeBuiltInValidation({
2095
+ fields: _fields,
2096
+ onlyCheckValid: true,
2097
+ name: name,
2098
+ eventType: event.type,
2099
+ });
1889
2100
  }
1890
2101
  }
1891
2102
  }
@@ -1918,12 +2129,19 @@ function createFormControl(props = {}) {
1918
2129
  else if (name) {
1919
2130
  validationResult = (await Promise.all(fieldNames.map(async (fieldName) => {
1920
2131
  const field = get(_fields, fieldName);
1921
- return await executeBuiltInValidation(field && field._f ? { [fieldName]: field } : field);
2132
+ return await executeBuiltInValidation({
2133
+ fields: field && field._f ? { [fieldName]: field } : field,
2134
+ eventType: EVENTS.TRIGGER,
2135
+ });
1922
2136
  }))).every(Boolean);
1923
2137
  !(!validationResult && !_formState.isValid) && _setValid();
1924
2138
  }
1925
2139
  else {
1926
- validationResult = isValid = await executeBuiltInValidation(_fields);
2140
+ validationResult = isValid = await executeBuiltInValidation({
2141
+ fields: _fields,
2142
+ name,
2143
+ eventType: EVENTS.TRIGGER,
2144
+ });
1927
2145
  }
1928
2146
  _subjects.state.next({
1929
2147
  ...(!isString(name) ||
@@ -1960,11 +2178,24 @@ function createFormControl(props = {}) {
1960
2178
  isTouched: !!get((formState || _formState).touchedFields, name),
1961
2179
  });
1962
2180
  const clearErrors = (name) => {
1963
- name &&
1964
- convertToArrayPayload(name).forEach((inputName) => unset(_formState.errors, inputName));
1965
- _subjects.state.next({
1966
- errors: name ? _formState.errors : {},
1967
- });
2181
+ const names = name ? convertToArrayPayload(name) : undefined;
2182
+ names?.forEach((inputName) => unset(_formState.errors, inputName));
2183
+ if (names) {
2184
+ // Emit for each cleared field with the field name so that
2185
+ // shouldSubscribeByName can filter and avoid broad re-renders
2186
+ names.forEach((inputName) => {
2187
+ _subjects.state.next({
2188
+ name: inputName,
2189
+ errors: _formState.errors,
2190
+ });
2191
+ });
2192
+ }
2193
+ else {
2194
+ // Clear all errors - emit without name to notify all subscribers
2195
+ _subjects.state.next({
2196
+ errors: {},
2197
+ });
2198
+ }
1968
2199
  };
1969
2200
  const setError = (name, error, options) => {
1970
2201
  const ref = (get(_fields, name, { _f: {} })._f || {}).ref;
@@ -1988,8 +2219,9 @@ function createFormControl(props = {}) {
1988
2219
  next: (formState) => {
1989
2220
  if (shouldSubscribeByName(props.name, formState.name, props.exact) &&
1990
2221
  shouldRenderFormState(formState, props.formState || _proxyFormState, _setFormState, props.reRenderRoot)) {
2222
+ const snapshot = { ..._formValues };
1991
2223
  props.callback({
1992
- values: { ..._formValues },
2224
+ values: snapshot,
1993
2225
  ..._formState,
1994
2226
  ...formState,
1995
2227
  defaultValues: _defaultValues,
@@ -2051,6 +2283,7 @@ function createFormControl(props = {}) {
2051
2283
  const register = (name, options = {}) => {
2052
2284
  let field = get(_fields, name);
2053
2285
  const disabledIsDefined = isBoolean(options.disabled) || isBoolean(_options.disabled);
2286
+ const shouldRevalidateRemount = !_names.registerName.has(name) && field && field._f && !field._f.mount;
2054
2287
  set(_fields, name, {
2055
2288
  ...(field || {}),
2056
2289
  _f: {
@@ -2061,7 +2294,7 @@ function createFormControl(props = {}) {
2061
2294
  },
2062
2295
  });
2063
2296
  _names.mount.add(name);
2064
- if (field) {
2297
+ if (field && !shouldRevalidateRemount) {
2065
2298
  _setDisabledField({
2066
2299
  disabled: isBoolean(options.disabled)
2067
2300
  ? options.disabled
@@ -2091,7 +2324,9 @@ function createFormControl(props = {}) {
2091
2324
  onBlur: onChange,
2092
2325
  ref: (ref) => {
2093
2326
  if (ref) {
2327
+ _names.registerName.add(name);
2094
2328
  register(name, options);
2329
+ _names.registerName.delete(name);
2095
2330
  field = get(_fields, name);
2096
2331
  const fieldRef = isUndefined(ref.value)
2097
2332
  ? ref.querySelectorAll
@@ -2128,13 +2363,15 @@ function createFormControl(props = {}) {
2128
2363
  field._f.mount = false;
2129
2364
  }
2130
2365
  (_options.shouldUnregister || options.shouldUnregister) &&
2131
- !(isNameInFieldArray(_names.array, name) && _state.action) &&
2366
+ !(getFieldArrayParentNames(_names.array, name).length &&
2367
+ _state.action) &&
2132
2368
  _names.unMount.add(name);
2133
2369
  }
2134
2370
  },
2135
2371
  };
2136
2372
  };
2137
2373
  const _focusError = () => _options.shouldFocusError &&
2374
+ !_options.shouldUseNativeValidation &&
2138
2375
  iterateFieldsByAction(_fields, _focusInput, _names.mount);
2139
2376
  const _disableForm = (disabled) => {
2140
2377
  if (isBoolean(disabled)) {
@@ -2170,14 +2407,17 @@ function createFormControl(props = {}) {
2170
2407
  fieldValues = cloneObject(values);
2171
2408
  }
2172
2409
  else {
2173
- await executeBuiltInValidation(_fields);
2410
+ await executeBuiltInValidation({
2411
+ fields: _fields,
2412
+ eventType: EVENTS.SUBMIT,
2413
+ });
2174
2414
  }
2175
2415
  if (_names.disabled.size) {
2176
2416
  for (const name of _names.disabled) {
2177
2417
  unset(fieldValues, name);
2178
2418
  }
2179
2419
  }
2180
- unset(_formState.errors, 'root');
2420
+ unset(_formState.errors, ROOT_ERROR_TYPE);
2181
2421
  if (isEmptyObject(_formState.errors)) {
2182
2422
  _subjects.state.next({
2183
2423
  errors: {},
@@ -2301,6 +2541,7 @@ function createFormControl(props = {}) {
2301
2541
  mount: keepStateOptions.keepDirtyValues ? _names.mount : new Set(),
2302
2542
  unMount: new Set(),
2303
2543
  array: new Set(),
2544
+ registerName: new Set(),
2304
2545
  disabled: new Set(),
2305
2546
  watch: new Set(),
2306
2547
  watchAll: false,
@@ -2454,6 +2695,7 @@ function createFormControl(props = {}) {
2454
2695
  handleSubmit,
2455
2696
  watch,
2456
2697
  setValue,
2698
+ setValues,
2457
2699
  getValues,
2458
2700
  reset,
2459
2701
  resetField,
@@ -2691,10 +2933,11 @@ function useFieldArray(props) {
2691
2933
  control._subjects.state.next({
2692
2934
  ...control._formState,
2693
2935
  });
2936
+ const validationModes = getValidationModes(control._options.mode);
2694
2937
  if (_actioned.current &&
2695
- (!getValidationModes(control._options.mode).isOnSubmit ||
2696
- control._formState.isSubmitted) &&
2697
- !getValidationModes(control._options.reValidateMode).isOnSubmit) {
2938
+ (!validationModes.isOnSubmit || control._formState.isSubmitted) &&
2939
+ !getValidationModes(control._options.reValidateMode).isOnSubmit &&
2940
+ !validationModes.isOnBlur) {
2698
2941
  if (control._options.resolver) {
2699
2942
  control._runSchema([name]).then((result) => {
2700
2943
  control._updateIsValidating([name]);
@@ -2749,15 +2992,22 @@ function useFieldArray(props) {
2749
2992
  React.useEffect(() => {
2750
2993
  !get(control._formValues, name) && control._setFieldArray(name);
2751
2994
  return () => {
2995
+ const shouldKeepFieldArrayValues = !(control._options.shouldUnregister || shouldUnregister);
2752
2996
  const updateMounted = (name, value) => {
2753
2997
  const field = get(control._fields, name);
2754
2998
  if (field && field._f) {
2755
2999
  field._f.mount = value;
2756
3000
  }
2757
3001
  };
2758
- control._options.shouldUnregister || shouldUnregister
2759
- ? control.unregister(name)
2760
- : updateMounted(name, false);
3002
+ if (_actioned.current && shouldKeepFieldArrayValues) {
3003
+ control._subjects.state.next({
3004
+ name,
3005
+ values: cloneObject(control._formValues),
3006
+ });
3007
+ }
3008
+ shouldKeepFieldArrayValues
3009
+ ? updateMounted(name, false)
3010
+ : control.unregister(name);
2761
3011
  };
2762
3012
  }, [name, control, shouldUnregister]);
2763
3013
  return {
@@ -2819,25 +3069,15 @@ function updateMethodsReference(_formControl) {
2819
3069
  function useForm(props = {}) {
2820
3070
  const _formControl = React.useRef(undefined);
2821
3071
  const _values = React.useRef(undefined);
2822
- const [formState, updateFormState] = React.useState({
2823
- isDirty: false,
2824
- isValidating: false,
3072
+ const [formState, updateFormState] = React.useState(() => ({
3073
+ ...cloneObject(DEFAULT_FORM_STATE),
2825
3074
  isLoading: isFunction(props.defaultValues),
2826
- isSubmitted: false,
2827
- isSubmitting: false,
2828
- isSubmitSuccessful: false,
2829
- isValid: false,
2830
- submitCount: 0,
2831
- dirtyFields: {},
2832
- touchedFields: {},
2833
- validatingFields: {},
2834
3075
  errors: props.errors || {},
2835
3076
  disabled: props.disabled || false,
2836
- isReady: false,
2837
3077
  defaultValues: isFunction(props.defaultValues)
2838
3078
  ? undefined
2839
3079
  : props.defaultValues,
2840
- });
3080
+ }));
2841
3081
  if (!_formControl.current) {
2842
3082
  if (props.formControl) {
2843
3083
  _formControl.current = {
@@ -2861,7 +3101,10 @@ function useForm(props = {}) {
2861
3101
  useIsomorphicLayoutEffect(() => {
2862
3102
  const sub = control._subscribe({
2863
3103
  formState: control._proxyFormState,
2864
- callback: () => updateFormState({ ...control._formState }),
3104
+ callback: () => updateFormState({
3105
+ ...control._formState,
3106
+ defaultValues: control._defaultValues,
3107
+ }),
2865
3108
  reRenderRoot: true,
2866
3109
  });
2867
3110
  updateFormState((data) => ({
@@ -2903,14 +3146,13 @@ function useForm(props = {}) {
2903
3146
  }
2904
3147
  }, [control, formState.isDirty]);
2905
3148
  React.useEffect(() => {
2906
- var _a;
2907
3149
  if (props.values && !deepEqual(props.values, _values.current)) {
2908
3150
  updateMethodsReference(_formControl);
2909
3151
  control._reset(props.values, {
2910
3152
  keepFieldsRef: true,
2911
3153
  ...control._options.resetOptions,
2912
3154
  });
2913
- if (!((_a = control._options.resetOptions) === null || _a === void 0 ? void 0 : _a.keepIsValid)) {
3155
+ if (!control._options.resetOptions?.keepIsValid) {
2914
3156
  control._setValid();
2915
3157
  }
2916
3158
  _values.current = props.values;