react-hook-form 7.40.0-next.1 → 7.40.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.
@@ -122,7 +122,10 @@ const useFormContext = () => React.useContext(HookFormContext);
122
122
  * }
123
123
  * ```
124
124
  */
125
- const FormProvider = ({ children, ...data }) => (React.createElement(HookFormContext.Provider, { value: React.useState(data)[0] }, children));
125
+ const FormProvider = (props) => {
126
+ const { children, ...data } = props;
127
+ return (React.createElement(HookFormContext.Provider, { value: data }, children));
128
+ };
126
129
 
127
130
  var getProxyFormState = (formState, control, localProxyFormState, isRoot = true) => {
128
131
  const result = {
@@ -170,7 +173,7 @@ function useSubscribe(props) {
170
173
  React.useEffect(() => {
171
174
  const subscription = !props.disabled &&
172
175
  _props.current.subject.subscribe({
173
- next: _props.current.next,
176
+ next: _props.current.callback,
174
177
  });
175
178
  return () => {
176
179
  subscription && subscription.unsubscribe();
@@ -225,13 +228,13 @@ function useFormState(props) {
225
228
  _name.current = name;
226
229
  useSubscribe({
227
230
  disabled,
228
- next: (value) => _mounted.current &&
231
+ callback: React.useCallback((value) => _mounted.current &&
229
232
  shouldSubscribeByName(_name.current, value.name, exact) &&
230
233
  shouldRenderFormState(value, _localProxyFormState.current) &&
231
234
  updateFormState({
232
235
  ...control._formState,
233
236
  ...value,
234
- }),
237
+ }), [control, exact]),
235
238
  subject: control._subjects.state,
236
239
  });
237
240
  React.useEffect(() => {
@@ -260,7 +263,7 @@ var generateWatchOutput = (names, _names, formValues, isGlobal) => {
260
263
  if (Array.isArray(names)) {
261
264
  return names.map((fieldName) => (isGlobal && _names.watch.add(fieldName), get(formValues, fieldName)));
262
265
  }
263
- _names.watchAll = !!isGlobal;
266
+ isGlobal && (_names.watchAll = true);
264
267
  return formValues;
265
268
  };
266
269
 
@@ -324,14 +327,10 @@ function useWatch(props) {
324
327
  useSubscribe({
325
328
  disabled,
326
329
  subject: control._subjects.watch,
327
- next: (formState) => {
330
+ callback: (formState) => {
328
331
  if (shouldSubscribeByName(_name.current, formState.name, exact)) {
329
332
  const fieldValues = generateWatchOutput(_name.current, control._names, formState.values || control._formValues);
330
- updateValue(isUndefined(_name.current) || !isUndefined(fieldValues)
331
- ? cloneObject(fieldValues)
332
- : isUndefined(fieldValues)
333
- ? defaultValue
334
- : fieldValues);
333
+ updateValue(isUndefined(fieldValues) ? defaultValue : cloneObject(fieldValues));
335
334
  }
336
335
  },
337
336
  });
@@ -981,16 +980,17 @@ function useFieldArray(props) {
981
980
  control._names.array.add(name);
982
981
  props.rules &&
983
982
  control.register(name, props.rules);
984
- useSubscribe({
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
- }
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);
992
989
  }
993
- },
990
+ }
991
+ }, []);
992
+ useSubscribe({
993
+ callback,
994
994
  subject: control._subjects.array,
995
995
  });
996
996
  const updateValues = React.useCallback((updatedFieldArrayValues) => {
@@ -1115,7 +1115,7 @@ function useFieldArray(props) {
1115
1115
  values: control._formValues,
1116
1116
  });
1117
1117
  control._names.focus &&
1118
- focusFieldBy(control._fields, (key) => !!key && key.startsWith(control._names.focus));
1118
+ focusFieldBy(control._fields, (key) => !!key && key.startsWith(control._names.focus || ''));
1119
1119
  control._names.focus = '';
1120
1120
  control._proxyFormState.isValid && control._updateValid();
1121
1121
  }, [fields, name, control]);
@@ -1205,8 +1205,8 @@ function deepEqual(object1, object2) {
1205
1205
 
1206
1206
  var isHTMLElement = (value) => {
1207
1207
  const owner = value ? value.ownerDocument : 0;
1208
- return (value instanceof
1209
- (owner && owner.defaultView ? owner.defaultView.HTMLElement : HTMLElement));
1208
+ const ElementClass = owner && owner.defaultView ? owner.defaultView.HTMLElement : HTMLElement;
1209
+ return value instanceof ElementClass;
1210
1210
  };
1211
1211
 
1212
1212
  var isMultipleSelect = (element) => element.type === `select-multiple`;
@@ -1391,7 +1391,6 @@ function createFormControl(props = {}) {
1391
1391
  ...defaultOptions,
1392
1392
  ...props,
1393
1393
  };
1394
- const shouldCaptureDirtyFields = props.resetOptions && props.resetOptions.keepDirtyValues;
1395
1394
  let _formState = {
1396
1395
  submitCount: 0,
1397
1396
  isDirty: false,
@@ -1405,9 +1404,7 @@ function createFormControl(props = {}) {
1405
1404
  errors: {},
1406
1405
  };
1407
1406
  let _fields = {};
1408
- let _defaultValues = isObject(_options.defaultValues)
1409
- ? cloneObject(_options.defaultValues) || {}
1410
- : {};
1407
+ let _defaultValues = cloneObject(_options.defaultValues) || {};
1411
1408
  let _formValues = _options.shouldUnregister
1412
1409
  ? {}
1413
1410
  : cloneObject(_defaultValues);
@@ -1424,7 +1421,6 @@ function createFormControl(props = {}) {
1424
1421
  };
1425
1422
  let delayErrorCallback;
1426
1423
  let timer = 0;
1427
- let validateFields = {};
1428
1424
  const _proxyFormState = {
1429
1425
  isDirty: false,
1430
1426
  dirtyFields: false,
@@ -1449,7 +1445,7 @@ function createFormControl(props = {}) {
1449
1445
  if (_proxyFormState.isValid) {
1450
1446
  const isValid = _options.resolver
1451
1447
  ? isEmptyObject((await _executeSchema()).errors)
1452
- : (await executeBuiltInValidation(_fields, true)).valid;
1448
+ : await executeBuiltInValidation(_fields, true);
1453
1449
  if (isValid !== _formState.isValid) {
1454
1450
  _formState.isValid = isValid;
1455
1451
  _subjects.state.next({
@@ -1458,6 +1454,11 @@ function createFormControl(props = {}) {
1458
1454
  }
1459
1455
  }
1460
1456
  };
1457
+ const _updateIsValidating = (value) => _proxyFormState.isValidating &&
1458
+ value !== _formState.isValidating &&
1459
+ _subjects.state.next({
1460
+ isValidating: value,
1461
+ });
1461
1462
  const _updateFieldArray = (name, values = [], method, args, shouldSetValues = true, shouldUpdateFieldsAndState = true) => {
1462
1463
  if (args && method) {
1463
1464
  _stateFlags.action = true;
@@ -1481,6 +1482,7 @@ function createFormControl(props = {}) {
1481
1482
  _formState.dirtyFields = getDirtyFields(_defaultValues, _formValues);
1482
1483
  }
1483
1484
  _subjects.state.next({
1485
+ name,
1484
1486
  isDirty: _getDirty(name, values),
1485
1487
  dirtyFields: _formState.dirtyFields,
1486
1488
  errors: _formState.errors,
@@ -1515,22 +1517,22 @@ function createFormControl(props = {}) {
1515
1517
  const output = {
1516
1518
  name,
1517
1519
  };
1518
- if (_proxyFormState.isDirty) {
1519
- isPreviousDirty = _formState.isDirty;
1520
- _formState.isDirty = output.isDirty = _getDirty();
1521
- shouldUpdateField = isPreviousDirty !== output.isDirty;
1522
- }
1523
1520
  if (!isBlurEvent || shouldDirty) {
1524
- const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
1525
- isPreviousDirty = get(_formState.dirtyFields, name);
1526
- isCurrentFieldPristine
1527
- ? unset(_formState.dirtyFields, name)
1528
- : set(_formState.dirtyFields, name, true);
1529
- output.dirtyFields = _formState.dirtyFields;
1530
- shouldUpdateField =
1531
- shouldUpdateField ||
1532
- (_proxyFormState.dirtyFields &&
1533
- isPreviousDirty !== !isCurrentFieldPristine);
1521
+ if (_proxyFormState.isDirty) {
1522
+ isPreviousDirty = _formState.isDirty;
1523
+ _formState.isDirty = output.isDirty = _getDirty();
1524
+ shouldUpdateField = isPreviousDirty !== output.isDirty;
1525
+ }
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
+ }
1534
1536
  }
1535
1537
  if (isBlurEvent) {
1536
1538
  const isPreviousFieldTouched = get(_formState.touchedFields, name);
@@ -1577,18 +1579,9 @@ function createFormControl(props = {}) {
1577
1579
  };
1578
1580
  _subjects.state.next(updatedFormState);
1579
1581
  }
1580
- validateFields[name]--;
1581
- if (_proxyFormState.isValidating &&
1582
- !Object.values(validateFields).some((v) => v)) {
1583
- _subjects.state.next({
1584
- isValidating: false,
1585
- });
1586
- validateFields = {};
1587
- }
1582
+ _updateIsValidating(false);
1588
1583
  };
1589
- const _executeSchema = async (name) => _options.resolver
1590
- ? await _options.resolver({ ..._formValues }, _options.context, getResolverOptions(name || _names.mount, _fields, _options.criteriaMode, _options.shouldUseNativeValidation))
1591
- : {};
1584
+ const _executeSchema = async (name) => await _options.resolver(_formValues, _options.context, getResolverOptions(name || _names.mount, _fields, _options.criteriaMode, _options.shouldUseNativeValidation));
1592
1585
  const executeSchemaAndUpdateState = async (names) => {
1593
1586
  const { errors } = await _executeSchema();
1594
1587
  if (names) {
@@ -1615,9 +1608,6 @@ function createFormControl(props = {}) {
1615
1608
  const isFieldArrayRoot = _names.array.has(_f.name);
1616
1609
  const fieldError = await validateField(field, get(_formValues, _f.name), shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation, isFieldArrayRoot);
1617
1610
  if (fieldError[_f.name]) {
1618
- if (_f.name === context.name) {
1619
- context.error = fieldError[context.name];
1620
- }
1621
1611
  context.valid = false;
1622
1612
  if (shouldOnlyCheckValid) {
1623
1613
  break;
@@ -1634,7 +1624,7 @@ function createFormControl(props = {}) {
1634
1624
  (await executeBuiltInValidation(fieldValue, shouldOnlyCheckValid, context));
1635
1625
  }
1636
1626
  }
1637
- return context;
1627
+ return context.valid;
1638
1628
  };
1639
1629
  const _removeUnmounted = () => {
1640
1630
  for (const name of _names.unMount) {
@@ -1703,8 +1693,7 @@ function createFormControl(props = {}) {
1703
1693
  }
1704
1694
  (options.shouldDirty || options.shouldTouch) &&
1705
1695
  updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty, true);
1706
- options.shouldValidate &&
1707
- trigger(name);
1696
+ options.shouldValidate && trigger(name);
1708
1697
  };
1709
1698
  const setValues = (name, value, options) => {
1710
1699
  for (const fieldKey in value) {
@@ -1753,12 +1742,11 @@ function createFormControl(props = {}) {
1753
1742
  const target = event.target;
1754
1743
  let name = target.name;
1755
1744
  const field = get(_fields, name);
1745
+ const getCurrentFieldValue = () => target.type ? getFieldValue(field._f) : getEventValue(event);
1756
1746
  if (field) {
1757
1747
  let error;
1758
1748
  let isValid;
1759
- const fieldValue = target.type
1760
- ? getFieldValue(field._f)
1761
- : getEventValue(event);
1749
+ const fieldValue = getCurrentFieldValue();
1762
1750
  const isBlurEvent = event.type === EVENTS.BLUR || event.type === EVENTS.FOCUS_OUT;
1763
1751
  const shouldSkipValidation = (!hasValidation(field._f) &&
1764
1752
  !_options.resolver &&
@@ -1787,12 +1775,7 @@ function createFormControl(props = {}) {
1787
1775
  _subjects.state.next({ name, ...(watched ? {} : fieldState) }));
1788
1776
  }
1789
1777
  !isBlurEvent && watched && _subjects.state.next({});
1790
- validateFields[name] = validateFields[name]
1791
- ? validateFields[name] + 1
1792
- : 1;
1793
- _subjects.state.next({
1794
- isValidating: true,
1795
- });
1778
+ _updateIsValidating(true);
1796
1779
  if (_options.resolver) {
1797
1780
  const { errors } = await _executeSchema([name]);
1798
1781
  const previousErrorLookupResult = schemaErrorLookup(_formState.errors, _fields, name);
@@ -1802,30 +1785,29 @@ function createFormControl(props = {}) {
1802
1785
  isValid = isEmptyObject(errors);
1803
1786
  }
1804
1787
  else {
1805
- if (_proxyFormState.isValid) {
1806
- const buildInValidationResult = await executeBuiltInValidation(_fields, true, {
1807
- name,
1808
- valid: true,
1809
- });
1810
- error = buildInValidationResult.error || {};
1811
- isValid = buildInValidationResult.valid;
1788
+ error = (await validateField(field, get(_formValues, name), shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation))[name];
1789
+ if (error) {
1790
+ isValid = false;
1812
1791
  }
1813
- if (!error || isEmptyObject(error)) {
1814
- error = (await validateField(field, get(_formValues, name), shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation))[name];
1792
+ else if (_proxyFormState.isValid) {
1793
+ isValid = await executeBuiltInValidation(_fields, true);
1815
1794
  }
1816
1795
  }
1817
- field._f.deps &&
1818
- trigger(field._f.deps);
1819
- shouldRenderByError(name, isValid, error, fieldState);
1796
+ if (!isPrimitive(fieldValue) || getCurrentFieldValue() === fieldValue) {
1797
+ field._f.deps &&
1798
+ trigger(field._f.deps);
1799
+ shouldRenderByError(name, isValid, error, fieldState);
1800
+ }
1801
+ else {
1802
+ _updateIsValidating(false);
1803
+ }
1820
1804
  }
1821
1805
  };
1822
1806
  const trigger = async (name, options = {}) => {
1823
1807
  let isValid;
1824
1808
  let validationResult;
1825
1809
  const fieldNames = convertToArrayPayload(name);
1826
- _subjects.state.next({
1827
- isValidating: true,
1828
- });
1810
+ _updateIsValidating(true);
1829
1811
  if (_options.resolver) {
1830
1812
  const errors = await executeSchemaAndUpdateState(isUndefined(name) ? name : fieldNames);
1831
1813
  isValid = isEmptyObject(errors);
@@ -1836,13 +1818,12 @@ function createFormControl(props = {}) {
1836
1818
  else if (name) {
1837
1819
  validationResult = (await Promise.all(fieldNames.map(async (fieldName) => {
1838
1820
  const field = get(_fields, fieldName);
1839
- return (await executeBuiltInValidation(field && field._f ? { [fieldName]: field } : field)).valid;
1821
+ return await executeBuiltInValidation(field && field._f ? { [fieldName]: field } : field);
1840
1822
  }))).every(Boolean);
1841
1823
  !(!validationResult && !_formState.isValid) && _updateValid();
1842
1824
  }
1843
1825
  else {
1844
- validationResult = isValid = (await executeBuiltInValidation(_fields))
1845
- .valid;
1826
+ validationResult = isValid = await executeBuiltInValidation(_fields);
1846
1827
  }
1847
1828
  _subjects.state.next({
1848
1829
  ...(!isString(name) ||
@@ -1898,7 +1879,7 @@ function createFormControl(props = {}) {
1898
1879
  };
1899
1880
  const watch = (name, defaultValue) => isFunction(name)
1900
1881
  ? _subjects.watch.subscribe({
1901
- next: (info) => name(_getWatch(undefined, defaultValue), info),
1882
+ next: (payload) => name(_getWatch(undefined, defaultValue), payload),
1902
1883
  })
1903
1884
  : _getWatch(name, defaultValue, true);
1904
1885
  const unregister = (name, options = {}) => {
@@ -1983,9 +1964,7 @@ function createFormControl(props = {}) {
1983
1964
  refs: [
1984
1965
  ...refs.filter(live),
1985
1966
  fieldRef,
1986
- ...(!!Array.isArray(get(_defaultValues, name))
1987
- ? [{}]
1988
- : []),
1967
+ ...(Array.isArray(get(_defaultValues, name)) ? [{}] : []),
1989
1968
  ],
1990
1969
  ref: { type: fieldRef.type, name },
1991
1970
  }
@@ -2091,7 +2070,7 @@ function createFormControl(props = {}) {
2091
2070
  _defaultValues = updatedValues;
2092
2071
  }
2093
2072
  if (!keepStateOptions.keepValues) {
2094
- if (keepStateOptions.keepDirtyValues || shouldCaptureDirtyFields) {
2073
+ if (keepStateOptions.keepDirtyValues) {
2095
2074
  for (const fieldName of _names.mount) {
2096
2075
  get(_formState.dirtyFields, fieldName)
2097
2076
  ? set(values, fieldName, get(_formValues, fieldName))
@@ -2181,11 +2160,6 @@ function createFormControl(props = {}) {
2181
2160
  }
2182
2161
  }
2183
2162
  };
2184
- if (isFunction(_options.defaultValues)) {
2185
- _options.defaultValues().then((values) => {
2186
- reset(values, _options.resetOptions);
2187
- });
2188
- }
2189
2163
  return {
2190
2164
  control: {
2191
2165
  register,
@@ -2199,7 +2173,6 @@ function createFormControl(props = {}) {
2199
2173
  _removeUnmounted,
2200
2174
  _updateFieldArray,
2201
2175
  _getFieldArray,
2202
- _reset,
2203
2176
  _subjects,
2204
2177
  _proxyFormState,
2205
2178
  get _fields() {
@@ -2297,9 +2270,7 @@ function useForm(props = {}) {
2297
2270
  dirtyFields: {},
2298
2271
  touchedFields: {},
2299
2272
  errors: {},
2300
- defaultValues: isFunction(props.defaultValues)
2301
- ? undefined
2302
- : props.defaultValues,
2273
+ defaultValues: props.defaultValues,
2303
2274
  });
2304
2275
  if (!_formControl.current) {
2305
2276
  _formControl.current = {
@@ -2311,7 +2282,7 @@ function useForm(props = {}) {
2311
2282
  control._options = props;
2312
2283
  useSubscribe({
2313
2284
  subject: control._subjects.state,
2314
- next: (value) => {
2285
+ callback: React.useCallback((value) => {
2315
2286
  if (shouldRenderFormState(value, control._proxyFormState, true)) {
2316
2287
  control._formState = {
2317
2288
  ...control._formState,
@@ -2319,7 +2290,7 @@ function useForm(props = {}) {
2319
2290
  };
2320
2291
  updateFormState({ ...control._formState });
2321
2292
  }
2322
- },
2293
+ }, [control]),
2323
2294
  });
2324
2295
  React.useEffect(() => {
2325
2296
  if (!control._stateFlags.mount) {
@@ -2332,11 +2303,6 @@ function useForm(props = {}) {
2332
2303
  }
2333
2304
  control._removeUnmounted();
2334
2305
  });
2335
- React.useEffect(() => {
2336
- if (props.values && !deepEqual(props.values, control._defaultValues)) {
2337
- control._reset(props.values, control._options.resetOptions);
2338
- }
2339
- }, [props.values, control]);
2340
2306
  React.useEffect(() => {
2341
2307
  formState.submitCount && control._focusError();
2342
2308
  }, [control, formState.submitCount]);