react-hook-form 7.40.0 → 7.41.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 (104) hide show
  1. package/dist/__tests__/controller.server.test.d.ts +2 -0
  2. package/dist/__tests__/controller.server.test.d.ts.map +1 -0
  3. package/dist/__tests__/controller.test.d.ts +2 -0
  4. package/dist/__tests__/controller.test.d.ts.map +1 -0
  5. package/dist/__tests__/logic/validateField.test.d.ts +2 -0
  6. package/dist/__tests__/logic/validateField.test.d.ts.map +1 -0
  7. package/dist/__tests__/type.test.d.ts +2 -0
  8. package/dist/__tests__/type.test.d.ts.map +1 -0
  9. package/dist/__tests__/useController.test.d.ts +2 -0
  10. package/dist/__tests__/useController.test.d.ts.map +1 -0
  11. package/dist/__tests__/useFieldArray/append.test.d.ts +2 -0
  12. package/dist/__tests__/useFieldArray/append.test.d.ts.map +1 -0
  13. package/dist/__tests__/useFieldArray/focus.test.d.ts +2 -0
  14. package/dist/__tests__/useFieldArray/focus.test.d.ts.map +1 -0
  15. package/dist/__tests__/useFieldArray/insert.test.d.ts +2 -0
  16. package/dist/__tests__/useFieldArray/insert.test.d.ts.map +1 -0
  17. package/dist/__tests__/useFieldArray/move.test.d.ts +2 -0
  18. package/dist/__tests__/useFieldArray/move.test.d.ts.map +1 -0
  19. package/dist/__tests__/useFieldArray/prepend.test.d.ts +2 -0
  20. package/dist/__tests__/useFieldArray/prepend.test.d.ts.map +1 -0
  21. package/dist/__tests__/useFieldArray/remove.test.d.ts +2 -0
  22. package/dist/__tests__/useFieldArray/remove.test.d.ts.map +1 -0
  23. package/dist/__tests__/useFieldArray/replace.test.d.ts +2 -0
  24. package/dist/__tests__/useFieldArray/replace.test.d.ts.map +1 -0
  25. package/dist/__tests__/useFieldArray/swap.test.d.ts +2 -0
  26. package/dist/__tests__/useFieldArray/swap.test.d.ts.map +1 -0
  27. package/dist/__tests__/useFieldArray/update.test.d.ts +2 -0
  28. package/dist/__tests__/useFieldArray/update.test.d.ts.map +1 -0
  29. package/dist/__tests__/useFieldArray.test.d.ts +2 -0
  30. package/dist/__tests__/useFieldArray.test.d.ts.map +1 -0
  31. package/dist/__tests__/useForm/clearErrors.test.d.ts +2 -0
  32. package/dist/__tests__/useForm/clearErrors.test.d.ts.map +1 -0
  33. package/dist/__tests__/useForm/formState.test.d.ts +2 -0
  34. package/dist/__tests__/useForm/formState.test.d.ts.map +1 -0
  35. package/dist/__tests__/useForm/getFieldState.test.d.ts +2 -0
  36. package/dist/__tests__/useForm/getFieldState.test.d.ts.map +1 -0
  37. package/dist/__tests__/useForm/getValues.test.d.ts +2 -0
  38. package/dist/__tests__/useForm/getValues.test.d.ts.map +1 -0
  39. package/dist/__tests__/useForm/handleSubmit.test.d.ts +2 -0
  40. package/dist/__tests__/useForm/handleSubmit.test.d.ts.map +1 -0
  41. package/dist/__tests__/useForm/register.test.d.ts +2 -0
  42. package/dist/__tests__/useForm/register.test.d.ts.map +1 -0
  43. package/dist/__tests__/useForm/reset.test.d.ts +2 -0
  44. package/dist/__tests__/useForm/reset.test.d.ts.map +1 -0
  45. package/dist/__tests__/useForm/resetField.test.d.ts +2 -0
  46. package/dist/__tests__/useForm/resetField.test.d.ts.map +1 -0
  47. package/dist/__tests__/useForm/resolver.test.d.ts +2 -0
  48. package/dist/__tests__/useForm/resolver.test.d.ts.map +1 -0
  49. package/dist/__tests__/useForm/setError.test.d.ts +2 -0
  50. package/dist/__tests__/useForm/setError.test.d.ts.map +1 -0
  51. package/dist/__tests__/useForm/setValue.test.d.ts +2 -0
  52. package/dist/__tests__/useForm/setValue.test.d.ts.map +1 -0
  53. package/dist/__tests__/useForm/trigger.test.d.ts +2 -0
  54. package/dist/__tests__/useForm/trigger.test.d.ts.map +1 -0
  55. package/dist/__tests__/useForm/unregister.test.d.ts +2 -0
  56. package/dist/__tests__/useForm/unregister.test.d.ts.map +1 -0
  57. package/dist/__tests__/useForm/watch.test.d.ts +2 -0
  58. package/dist/__tests__/useForm/watch.test.d.ts.map +1 -0
  59. package/dist/__tests__/useForm.server.test.d.ts +2 -0
  60. package/dist/__tests__/useForm.server.test.d.ts.map +1 -0
  61. package/dist/__tests__/useForm.test.d.ts +2 -0
  62. package/dist/__tests__/useForm.test.d.ts.map +1 -0
  63. package/dist/__tests__/useFormContext.server.test.d.ts +2 -0
  64. package/dist/__tests__/useFormContext.server.test.d.ts.map +1 -0
  65. package/dist/__tests__/useFormContext.test.d.ts +2 -0
  66. package/dist/__tests__/useFormContext.test.d.ts.map +1 -0
  67. package/dist/__tests__/useFormState.test.d.ts +2 -0
  68. package/dist/__tests__/useFormState.test.d.ts.map +1 -0
  69. package/dist/__tests__/useWatch.test.d.ts +2 -0
  70. package/dist/__tests__/useWatch.test.d.ts.map +1 -0
  71. package/dist/controller.d.ts +1 -1
  72. package/dist/controller.d.ts.map +1 -1
  73. package/dist/index.cjs.js +1 -1
  74. package/dist/index.cjs.js.map +1 -1
  75. package/dist/index.esm.mjs +70 -47
  76. package/dist/index.esm.mjs.map +1 -1
  77. package/dist/index.umd.js +1 -1
  78. package/dist/index.umd.js.map +1 -1
  79. package/dist/logic/createFormControl.d.ts +25 -2
  80. package/dist/logic/createFormControl.d.ts.map +1 -1
  81. package/dist/{utils → logic}/getValidationModes.d.ts +0 -0
  82. package/dist/{utils → logic}/getValidationModes.d.ts.map +1 -1
  83. package/dist/logic/updateFieldArrayRootError.d.ts +1 -1
  84. package/dist/logic/updateFieldArrayRootError.d.ts.map +1 -1
  85. package/dist/logic/validateField.d.ts.map +1 -1
  86. package/dist/types/errors.d.ts +2 -2
  87. package/dist/types/errors.d.ts.map +1 -1
  88. package/dist/types/form.d.ts +11 -7
  89. package/dist/types/form.d.ts.map +1 -1
  90. package/dist/types/path/eager.d.ts +5 -5
  91. package/dist/types/path/eager.d.ts.map +1 -1
  92. package/dist/types/utils.d.ts +1 -0
  93. package/dist/types/utils.d.ts.map +1 -1
  94. package/dist/types/validator.d.ts +1 -1
  95. package/dist/types/validator.d.ts.map +1 -1
  96. package/dist/useFieldArray.d.ts.map +1 -1
  97. package/dist/useForm.d.ts.map +1 -1
  98. package/dist/useFormContext.d.ts +1 -0
  99. package/dist/useFormContext.d.ts.map +1 -1
  100. package/dist/useFormState.d.ts.map +1 -1
  101. package/dist/useSubscribe.d.ts +1 -1
  102. package/dist/useSubscribe.d.ts.map +1 -1
  103. package/dist/utils/isHTMLElement.d.ts.map +1 -1
  104. package/package.json +18 -18
@@ -173,7 +173,7 @@ function useSubscribe(props) {
173
173
  React.useEffect(() => {
174
174
  const subscription = !props.disabled &&
175
175
  _props.current.subject.subscribe({
176
- next: _props.current.callback,
176
+ next: _props.current.next,
177
177
  });
178
178
  return () => {
179
179
  subscription && subscription.unsubscribe();
@@ -218,6 +218,7 @@ function useFormState(props) {
218
218
  const _mounted = React.useRef(true);
219
219
  const _localProxyFormState = React.useRef({
220
220
  isDirty: false,
221
+ isLoading: false,
221
222
  dirtyFields: false,
222
223
  touchedFields: false,
223
224
  isValidating: false,
@@ -228,13 +229,13 @@ function useFormState(props) {
228
229
  _name.current = name;
229
230
  useSubscribe({
230
231
  disabled,
231
- callback: React.useCallback((value) => _mounted.current &&
232
+ next: (value) => _mounted.current &&
232
233
  shouldSubscribeByName(_name.current, value.name, exact) &&
233
234
  shouldRenderFormState(value, _localProxyFormState.current) &&
234
235
  updateFormState({
235
236
  ...control._formState,
236
237
  ...value,
237
- }), [control, exact]),
238
+ }),
238
239
  subject: control._subjects.state,
239
240
  });
240
241
  React.useEffect(() => {
@@ -327,16 +328,14 @@ function useWatch(props) {
327
328
  useSubscribe({
328
329
  disabled,
329
330
  subject: control._subjects.watch,
330
- callback: (formState) => {
331
+ next: (formState) => {
331
332
  if (shouldSubscribeByName(_name.current, formState.name, exact)) {
332
333
  const fieldValues = generateWatchOutput(_name.current, control._names, formState.values || control._formValues);
333
334
  updateValue(isUndefined(fieldValues) ? defaultValue : cloneObject(fieldValues));
334
335
  }
335
336
  },
336
337
  });
337
- const [value, updateValue] = React.useState(isUndefined(defaultValue)
338
- ? control._getWatch(name)
339
- : defaultValue);
338
+ const [value, updateValue] = React.useState(control._getWatch(name, defaultValue));
340
339
  React.useEffect(() => control._removeUnmounted());
341
340
  return value;
342
341
  }
@@ -568,6 +567,14 @@ var getFocusFieldName = (name, index, options = {}) => options.shouldFocus || is
568
567
  `${name}.${isUndefined(options.focusIndex) ? index : options.focusIndex}.`
569
568
  : '';
570
569
 
570
+ var getValidationModes = (mode) => ({
571
+ isOnSubmit: !mode || mode === VALIDATION_MODE.onSubmit,
572
+ isOnBlur: mode === VALIDATION_MODE.onBlur,
573
+ isOnChange: mode === VALIDATION_MODE.onChange,
574
+ isOnAll: mode === VALIDATION_MODE.all,
575
+ isOnTouch: mode === VALIDATION_MODE.onTouched,
576
+ });
577
+
571
578
  var isWatched = (name, _names, isBlurEvent) => !isBlurEvent &&
572
579
  (_names.watchAll ||
573
580
  _names.watch.has(name) ||
@@ -666,7 +673,9 @@ var validateField = async (field, inputValue, validateAllFieldCriteria, shouldUs
666
673
  const isRadio = isRadioInput(ref);
667
674
  const isCheckBox = isCheckBoxInput(ref);
668
675
  const isRadioOrCheckbox = isRadio || isCheckBox;
669
- const isEmpty = ((valueAsNumber || isFileInput(ref)) && !ref.value) ||
676
+ const isEmpty = ((valueAsNumber || isFileInput(ref)) &&
677
+ isUndefined(ref.value) &&
678
+ isUndefined(inputValue)) ||
670
679
  inputValue === '' ||
671
680
  (Array.isArray(inputValue) && !inputValue.length);
672
681
  const appendErrorsCurry = appendErrors.bind(null, name, validateAllFieldCriteria, error);
@@ -831,14 +840,6 @@ function append(data, value) {
831
840
 
832
841
  var fillEmptyArray = (value) => Array.isArray(value) ? value.map(() => undefined) : undefined;
833
842
 
834
- var getValidationModes = (mode) => ({
835
- isOnSubmit: !mode || mode === VALIDATION_MODE.onSubmit,
836
- isOnBlur: mode === VALIDATION_MODE.onBlur,
837
- isOnChange: mode === VALIDATION_MODE.onChange,
838
- isOnAll: mode === VALIDATION_MODE.all,
839
- isOnTouch: mode === VALIDATION_MODE.onTouched,
840
- });
841
-
842
843
  function insert(data, index, value) {
843
844
  return [
844
845
  ...data.slice(0, index),
@@ -980,17 +981,16 @@ function useFieldArray(props) {
980
981
  control._names.array.add(name);
981
982
  props.rules &&
982
983
  control.register(name, props.rules);
983
- const callback = React.useCallback(({ values, name: fieldArrayName, }) => {
984
- if (fieldArrayName === _name.current || !fieldArrayName) {
985
- const fieldValues = get(values, _name.current);
986
- if (Array.isArray(fieldValues)) {
987
- setFields(fieldValues);
988
- ids.current = fieldValues.map(generateId);
989
- }
990
- }
991
- }, []);
992
984
  useSubscribe({
993
- callback,
985
+ next: ({ values, name: fieldArrayName, }) => {
986
+ if (fieldArrayName === _name.current || !fieldArrayName) {
987
+ const fieldValues = get(values, _name.current);
988
+ if (Array.isArray(fieldValues)) {
989
+ setFields(fieldValues);
990
+ ids.current = fieldValues.map(generateId);
991
+ }
992
+ }
993
+ },
994
994
  subject: control._subjects.array,
995
995
  });
996
996
  const updateValues = React.useCallback((updatedFieldArrayValues) => {
@@ -1205,8 +1205,8 @@ function deepEqual(object1, object2) {
1205
1205
 
1206
1206
  var isHTMLElement = (value) => {
1207
1207
  const owner = value ? value.ownerDocument : 0;
1208
- const ElementClass = owner && owner.defaultView ? owner.defaultView.HTMLElement : HTMLElement;
1209
- return value instanceof ElementClass;
1208
+ return (value instanceof
1209
+ (owner && owner.defaultView ? owner.defaultView.HTMLElement : HTMLElement));
1210
1210
  };
1211
1211
 
1212
1212
  var isMultipleSelect = (element) => element.type === `select-multiple`;
@@ -1386,14 +1386,16 @@ const defaultOptions = {
1386
1386
  reValidateMode: VALIDATION_MODE.onChange,
1387
1387
  shouldFocusError: true,
1388
1388
  };
1389
- function createFormControl(props = {}) {
1389
+ function createFormControl(props = {}, flushRootRender) {
1390
1390
  let _options = {
1391
1391
  ...defaultOptions,
1392
1392
  ...props,
1393
1393
  };
1394
+ const shouldCaptureDirtyFields = props.resetOptions && props.resetOptions.keepDirtyValues;
1394
1395
  let _formState = {
1395
1396
  submitCount: 0,
1396
1397
  isDirty: false,
1398
+ isLoading: true,
1397
1399
  isValidating: false,
1398
1400
  isSubmitted: false,
1399
1401
  isSubmitting: false,
@@ -1404,7 +1406,9 @@ function createFormControl(props = {}) {
1404
1406
  errors: {},
1405
1407
  };
1406
1408
  let _fields = {};
1407
- let _defaultValues = cloneObject(_options.defaultValues) || {};
1409
+ let _defaultValues = isObject(_options.defaultValues)
1410
+ ? cloneObject(_options.defaultValues) || {}
1411
+ : {};
1408
1412
  let _formValues = _options.shouldUnregister
1409
1413
  ? {}
1410
1414
  : cloneObject(_defaultValues);
@@ -1455,7 +1459,6 @@ function createFormControl(props = {}) {
1455
1459
  }
1456
1460
  };
1457
1461
  const _updateIsValidating = (value) => _proxyFormState.isValidating &&
1458
- value !== _formState.isValidating &&
1459
1462
  _subjects.state.next({
1460
1463
  isValidating: value,
1461
1464
  });
@@ -1523,16 +1526,16 @@ function createFormControl(props = {}) {
1523
1526
  _formState.isDirty = output.isDirty = _getDirty();
1524
1527
  shouldUpdateField = isPreviousDirty !== output.isDirty;
1525
1528
  }
1526
- if (_proxyFormState.dirtyFields) {
1527
- isPreviousDirty = get(_formState.dirtyFields, name);
1528
- const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
1529
- isCurrentFieldPristine
1530
- ? unset(_formState.dirtyFields, name)
1531
- : set(_formState.dirtyFields, name, true);
1532
- output.dirtyFields = _formState.dirtyFields;
1533
- shouldUpdateField =
1534
- shouldUpdateField || isPreviousDirty !== !isCurrentFieldPristine;
1535
- }
1529
+ const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
1530
+ isPreviousDirty = get(_formState.dirtyFields, name);
1531
+ isCurrentFieldPristine
1532
+ ? unset(_formState.dirtyFields, name)
1533
+ : set(_formState.dirtyFields, name, true);
1534
+ output.dirtyFields = _formState.dirtyFields;
1535
+ shouldUpdateField =
1536
+ shouldUpdateField ||
1537
+ (_proxyFormState.dirtyFields &&
1538
+ isPreviousDirty !== !isCurrentFieldPristine);
1536
1539
  }
1537
1540
  if (isBlurEvent) {
1538
1541
  const isPreviousFieldTouched = get(_formState.touchedFields, name);
@@ -1693,7 +1696,8 @@ function createFormControl(props = {}) {
1693
1696
  }
1694
1697
  (options.shouldDirty || options.shouldTouch) &&
1695
1698
  updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty, true);
1696
- options.shouldValidate && trigger(name);
1699
+ options.shouldValidate &&
1700
+ trigger(name);
1697
1701
  };
1698
1702
  const setValues = (name, value, options) => {
1699
1703
  for (const fieldKey in value) {
@@ -1737,6 +1741,7 @@ function createFormControl(props = {}) {
1737
1741
  _subjects.watch.next({
1738
1742
  name,
1739
1743
  });
1744
+ !_stateFlags.mount && flushRootRender();
1740
1745
  };
1741
1746
  const onChange = async (event) => {
1742
1747
  const target = event.target;
@@ -2070,7 +2075,7 @@ function createFormControl(props = {}) {
2070
2075
  _defaultValues = updatedValues;
2071
2076
  }
2072
2077
  if (!keepStateOptions.keepValues) {
2073
- if (keepStateOptions.keepDirtyValues) {
2078
+ if (keepStateOptions.keepDirtyValues || shouldCaptureDirtyFields) {
2074
2079
  for (const fieldName of _names.mount) {
2075
2080
  get(_formState.dirtyFields, fieldName)
2076
2081
  ? set(values, fieldName, get(_formValues, fieldName))
@@ -2117,6 +2122,7 @@ function createFormControl(props = {}) {
2117
2122
  watchAll: false,
2118
2123
  focus: '',
2119
2124
  };
2125
+ !_stateFlags.mount && flushRootRender();
2120
2126
  _stateFlags.mount =
2121
2127
  !_proxyFormState.isValid || !!keepStateOptions.keepIsValid;
2122
2128
  _stateFlags.watch = !!props.shouldUnregister;
@@ -2160,6 +2166,14 @@ function createFormControl(props = {}) {
2160
2166
  }
2161
2167
  }
2162
2168
  };
2169
+ if (isFunction(_options.defaultValues)) {
2170
+ _options.defaultValues().then((values) => {
2171
+ reset(values, _options.resetOptions);
2172
+ _subjects.state.next({
2173
+ isLoading: false,
2174
+ });
2175
+ });
2176
+ }
2163
2177
  return {
2164
2178
  control: {
2165
2179
  register,
@@ -2173,6 +2187,7 @@ function createFormControl(props = {}) {
2173
2187
  _removeUnmounted,
2174
2188
  _updateFieldArray,
2175
2189
  _getFieldArray,
2190
+ _reset,
2176
2191
  _subjects,
2177
2192
  _proxyFormState,
2178
2193
  get _fields() {
@@ -2262,6 +2277,7 @@ function useForm(props = {}) {
2262
2277
  const [formState, updateFormState] = React.useState({
2263
2278
  isDirty: false,
2264
2279
  isValidating: false,
2280
+ isLoading: true,
2265
2281
  isSubmitted: false,
2266
2282
  isSubmitting: false,
2267
2283
  isSubmitSuccessful: false,
@@ -2270,11 +2286,13 @@ function useForm(props = {}) {
2270
2286
  dirtyFields: {},
2271
2287
  touchedFields: {},
2272
2288
  errors: {},
2273
- defaultValues: props.defaultValues,
2289
+ defaultValues: isFunction(props.defaultValues)
2290
+ ? undefined
2291
+ : props.defaultValues,
2274
2292
  });
2275
2293
  if (!_formControl.current) {
2276
2294
  _formControl.current = {
2277
- ...createFormControl(props),
2295
+ ...createFormControl(props, () => updateFormState((formState) => ({ ...formState }))),
2278
2296
  formState,
2279
2297
  };
2280
2298
  }
@@ -2282,7 +2300,7 @@ function useForm(props = {}) {
2282
2300
  control._options = props;
2283
2301
  useSubscribe({
2284
2302
  subject: control._subjects.state,
2285
- callback: React.useCallback((value) => {
2303
+ next: (value) => {
2286
2304
  if (shouldRenderFormState(value, control._proxyFormState, true)) {
2287
2305
  control._formState = {
2288
2306
  ...control._formState,
@@ -2290,7 +2308,7 @@ function useForm(props = {}) {
2290
2308
  };
2291
2309
  updateFormState({ ...control._formState });
2292
2310
  }
2293
- }, [control]),
2311
+ },
2294
2312
  });
2295
2313
  React.useEffect(() => {
2296
2314
  if (!control._stateFlags.mount) {
@@ -2303,6 +2321,11 @@ function useForm(props = {}) {
2303
2321
  }
2304
2322
  control._removeUnmounted();
2305
2323
  });
2324
+ React.useEffect(() => {
2325
+ if (props.values && !deepEqual(props.values, control._defaultValues)) {
2326
+ control._reset(props.values, control._options.resetOptions);
2327
+ }
2328
+ }, [props.values, control]);
2306
2329
  React.useEffect(() => {
2307
2330
  formState.submitCount && control._focusError();
2308
2331
  }, [control, formState.submitCount]);