react-hook-form 7.75.0 → 7.76.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.
@@ -18,9 +18,15 @@ var getEventValue = (event) => isObject(event) && event.target
18
18
  : event.target.value
19
19
  : event;
20
20
 
21
- var isNameInFieldArray = (names, name) => name
22
- .split('.')
23
- .some((part, index, arr) => !isNaN(Number(part)) && names.has(arr.slice(0, index).join('.')));
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;
@@ -396,7 +402,8 @@ function useWatch(props) {
396
402
  function useController(props) {
397
403
  const formControl = useFormControlContext();
398
404
  const { name, disabled, control = formControl, shouldUnregister, defaultValue, exact = true, } = props;
399
- const isArrayField = isNameInFieldArray(control._names.array, name);
405
+ const isArrayField = !!getFieldArrayParentNames(control._names.array, name)
406
+ .length;
400
407
  const defaultValueMemo = React.useMemo(() => get(control._formValues, name, get(control._defaultValues, name, defaultValue)), [control, name, defaultValue]);
401
408
  const value = useWatch({
402
409
  control,
@@ -489,7 +496,7 @@ function useController(props) {
489
496
  };
490
497
  updateMounted(name, true);
491
498
  if (_shouldUnregisterField) {
492
- const value = cloneObject(get(control._options.defaultValues, name, _props.current.defaultValue));
499
+ const value = cloneObject(get(control._defaultValues, name, get(control._options.defaultValues, name, _props.current.defaultValue)));
493
500
  set(control._defaultValues, name, value);
494
501
  if (isUndefined(get(control._formValues, name))) {
495
502
  set(control._formValues, name, value);
@@ -1597,9 +1604,28 @@ function createFormControl(props = {}) {
1597
1604
  isValid: false,
1598
1605
  });
1599
1606
  };
1607
+ const hasExplicitNullIntermediate = (name) => {
1608
+ const segments = isKey(name) ? [name] : stringToPath(name);
1609
+ let formValues = _formValues;
1610
+ let defaultValues = _defaultValues;
1611
+ for (let i = 0; i < segments.length - 1; i++) {
1612
+ const key = segments[i];
1613
+ formValues = isNullOrUndefined(formValues) ? formValues : formValues[key];
1614
+ defaultValues = isNullOrUndefined(defaultValues)
1615
+ ? defaultValues
1616
+ : defaultValues[key];
1617
+ if (formValues === null && defaultValues !== null) {
1618
+ return true;
1619
+ }
1620
+ }
1621
+ return false;
1622
+ };
1600
1623
  const updateValidAndValue = (name, shouldSkipSetValueAs, value, ref) => {
1601
1624
  const field = get(_fields, name);
1602
1625
  if (field) {
1626
+ if (hasExplicitNullIntermediate(name)) {
1627
+ return;
1628
+ }
1603
1629
  const wasUnsetInFormValues = isUndefined(get(_formValues, name));
1604
1630
  const defaultValue = get(_formValues, name, isUndefined(value) ? get(_defaultValues, name) : value);
1605
1631
  isUndefined(defaultValue) ||
@@ -1642,9 +1668,14 @@ function createFormControl(props = {}) {
1642
1668
  }
1643
1669
  const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
1644
1670
  isPreviousDirty = !!get(_formState.dirtyFields, name);
1645
- isCurrentFieldPristine
1646
- ? unset(_formState.dirtyFields, name)
1647
- : set(_formState.dirtyFields, name, true);
1671
+ if (isCurrentFieldPristine !== _formState.isDirty) {
1672
+ _formState.dirtyFields = getDirtyFields(_defaultValues, _formValues);
1673
+ }
1674
+ else {
1675
+ isCurrentFieldPristine
1676
+ ? unset(_formState.dirtyFields, name)
1677
+ : set(_formState.dirtyFields, name, true);
1678
+ }
1648
1679
  output.dirtyFields = _formState.dirtyFields;
1649
1680
  shouldUpdateField =
1650
1681
  shouldUpdateField ||
@@ -1711,7 +1742,9 @@ function createFormControl(props = {}) {
1711
1742
  for (const name of names) {
1712
1743
  const error = get(errors, name);
1713
1744
  error
1714
- ? set(_formState.errors, name, error)
1745
+ ? _names.array.has(name) && isObject(error)
1746
+ ? updateFieldArrayRootError(_formState.errors, { [name]: error }, name)
1747
+ : set(_formState.errors, name, error)
1715
1748
  : unset(_formState.errors, name);
1716
1749
  }
1717
1750
  }
@@ -1733,8 +1766,8 @@ function createFormControl(props = {}) {
1733
1766
  const error = result[key];
1734
1767
  if (error) {
1735
1768
  setError(`${FORM_ERROR_TYPE}.${key}`, {
1736
- message: isString(result.message) ? result.message : '',
1737
- type: INPUT_VALIDATION_RULES.validate,
1769
+ message: isString(error.message) ? error.message : '',
1770
+ type: error.type || INPUT_VALIDATION_RULES.validate,
1738
1771
  });
1739
1772
  }
1740
1773
  }
@@ -1776,11 +1809,15 @@ function createFormControl(props = {}) {
1776
1809
  if (_f) {
1777
1810
  const isFieldArrayRoot = _names.array.has(_f.name);
1778
1811
  const isPromiseFunction = field._f && hasPromiseValidation(field._f);
1779
- if (isPromiseFunction && _proxyFormState.validatingFields) {
1812
+ const shouldTrackIsValidatingState = _proxyFormState.validatingFields ||
1813
+ _proxyFormState.isValidating ||
1814
+ _proxySubscribeFormState.validatingFields ||
1815
+ _proxySubscribeFormState.isValidating;
1816
+ if (isPromiseFunction && shouldTrackIsValidatingState) {
1780
1817
  _updateIsValidating([_f.name], true);
1781
1818
  }
1782
1819
  const fieldError = await validateField(field, _names.disabled, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation && !onlyCheckValid, isFieldArrayRoot);
1783
- if (isPromiseFunction && _proxyFormState.validatingFields) {
1820
+ if (isPromiseFunction && shouldTrackIsValidatingState) {
1784
1821
  _updateIsValidating([_f.name]);
1785
1822
  }
1786
1823
  if (fieldError[_f.name]) {
@@ -1908,7 +1945,9 @@ function createFormControl(props = {}) {
1908
1945
  const cloneValue = cloneObject(value);
1909
1946
  const previousValue = get(_formValues, name);
1910
1947
  const isValueUnchanged = deepEqual(previousValue, cloneValue);
1911
- set(_formValues, name, cloneValue);
1948
+ if (!isValueUnchanged) {
1949
+ set(_formValues, name, cloneValue);
1950
+ }
1912
1951
  if (isFieldArray) {
1913
1952
  _subjects.array.next({
1914
1953
  name,
@@ -1939,10 +1978,16 @@ function createFormControl(props = {}) {
1939
1978
  }
1940
1979
  if (!isValueUnchanged) {
1941
1980
  const watched = isWatched(name, _names);
1981
+ const values = cloneObject(_formValues);
1982
+ if (!isFieldArray) {
1983
+ for (const arrayName of getFieldArrayParentNames(_names.array, name)) {
1984
+ _subjects.array.next({ name: arrayName, values });
1985
+ }
1986
+ }
1942
1987
  _subjects.state.next({
1943
1988
  ...(watched && _formState),
1944
1989
  name: _state.mount || watched ? name : undefined,
1945
- values: cloneObject(_formValues),
1990
+ values,
1946
1991
  });
1947
1992
  }
1948
1993
  };
@@ -1955,6 +2000,9 @@ function createFormControl(props = {}) {
1955
2000
  ..._formValues,
1956
2001
  ...updatedFormValues,
1957
2002
  };
2003
+ for (const fieldName of _names.mount) {
2004
+ setValue(fieldName, get(updatedFormValues, fieldName));
2005
+ }
1958
2006
  _subjects.state.next({ ..._formState, values: _formValues });
1959
2007
  }
1960
2008
  };
@@ -2325,13 +2373,15 @@ function createFormControl(props = {}) {
2325
2373
  field._f.mount = false;
2326
2374
  }
2327
2375
  (_options.shouldUnregister || options.shouldUnregister) &&
2328
- !(isNameInFieldArray(_names.array, name) && _state.action) &&
2376
+ !(getFieldArrayParentNames(_names.array, name).length &&
2377
+ _state.action) &&
2329
2378
  _names.unMount.add(name);
2330
2379
  }
2331
2380
  },
2332
2381
  };
2333
2382
  };
2334
2383
  const _focusError = () => _options.shouldFocusError &&
2384
+ !_options.shouldUseNativeValidation &&
2335
2385
  iterateFieldsByAction(_fields, _focusInput, _names.mount);
2336
2386
  const _disableForm = (disabled) => {
2337
2387
  if (isBoolean(disabled)) {
@@ -3050,7 +3100,10 @@ function useForm(props = {}) {
3050
3100
  useIsomorphicLayoutEffect(() => {
3051
3101
  const sub = control._subscribe({
3052
3102
  formState: control._proxyFormState,
3053
- callback: () => updateFormState({ ...control._formState }),
3103
+ callback: () => updateFormState({
3104
+ ...control._formState,
3105
+ defaultValues: control._defaultValues,
3106
+ }),
3054
3107
  reRenderRoot: true,
3055
3108
  });
3056
3109
  updateFormState((data) => ({