react-hook-form 7.40.0-next.0 → 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.
@@ -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.next,
176
+ next: _props.current.callback,
177
177
  });
178
178
  return () => {
179
179
  subscription && subscription.unsubscribe();
@@ -228,13 +228,13 @@ function useFormState(props) {
228
228
  _name.current = name;
229
229
  useSubscribe({
230
230
  disabled,
231
- next: (value) => _mounted.current &&
231
+ callback: React.useCallback((value) => _mounted.current &&
232
232
  shouldSubscribeByName(_name.current, value.name, exact) &&
233
233
  shouldRenderFormState(value, _localProxyFormState.current) &&
234
234
  updateFormState({
235
235
  ...control._formState,
236
236
  ...value,
237
- }),
237
+ }), [control, exact]),
238
238
  subject: control._subjects.state,
239
239
  });
240
240
  React.useEffect(() => {
@@ -256,14 +256,12 @@ function useFormState(props) {
256
256
  var isString = (value) => typeof value === 'string';
257
257
 
258
258
  var generateWatchOutput = (names, _names, formValues, isGlobal) => {
259
- const isArray = Array.isArray(names);
260
259
  if (isString(names)) {
261
260
  isGlobal && _names.watch.add(names);
262
261
  return get(formValues, names);
263
262
  }
264
- if (isArray) {
265
- return names.map((fieldName) => (isGlobal && _names.watch.add(fieldName),
266
- get(formValues, fieldName)));
263
+ if (Array.isArray(names)) {
264
+ return names.map((fieldName) => (isGlobal && _names.watch.add(fieldName), get(formValues, fieldName)));
267
265
  }
268
266
  isGlobal && (_names.watchAll = true);
269
267
  return formValues;
@@ -329,14 +327,10 @@ function useWatch(props) {
329
327
  useSubscribe({
330
328
  disabled,
331
329
  subject: control._subjects.watch,
332
- next: (formState) => {
330
+ callback: (formState) => {
333
331
  if (shouldSubscribeByName(_name.current, formState.name, exact)) {
334
332
  const fieldValues = generateWatchOutput(_name.current, control._names, formState.values || control._formValues);
335
- updateValue(isUndefined(_name.current) || !isUndefined(fieldValues)
336
- ? cloneObject(fieldValues)
337
- : isUndefined(fieldValues)
338
- ? defaultValue
339
- : fieldValues);
333
+ updateValue(isUndefined(fieldValues) ? defaultValue : cloneObject(fieldValues));
340
334
  }
341
335
  },
342
336
  });
@@ -986,16 +980,17 @@ function useFieldArray(props) {
986
980
  control._names.array.add(name);
987
981
  props.rules &&
988
982
  control.register(name, props.rules);
989
- useSubscribe({
990
- next: ({ values, name: fieldArrayName, }) => {
991
- if (fieldArrayName === _name.current || !fieldArrayName) {
992
- const fieldValues = get(values, _name.current);
993
- if (Array.isArray(fieldValues)) {
994
- setFields(fieldValues);
995
- ids.current = fieldValues.map(generateId);
996
- }
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);
997
989
  }
998
- },
990
+ }
991
+ }, []);
992
+ useSubscribe({
993
+ callback,
999
994
  subject: control._subjects.array,
1000
995
  });
1001
996
  const updateValues = React.useCallback((updatedFieldArrayValues) => {
@@ -1120,7 +1115,7 @@ function useFieldArray(props) {
1120
1115
  values: control._formValues,
1121
1116
  });
1122
1117
  control._names.focus &&
1123
- focusFieldBy(control._fields, (key) => !!key && key.startsWith(control._names.focus));
1118
+ focusFieldBy(control._fields, (key) => !!key && key.startsWith(control._names.focus || ''));
1124
1119
  control._names.focus = '';
1125
1120
  control._proxyFormState.isValid && control._updateValid();
1126
1121
  }, [fields, name, control]);
@@ -1210,8 +1205,8 @@ function deepEqual(object1, object2) {
1210
1205
 
1211
1206
  var isHTMLElement = (value) => {
1212
1207
  const owner = value ? value.ownerDocument : 0;
1213
- return (value instanceof
1214
- (owner && owner.defaultView ? owner.defaultView.HTMLElement : HTMLElement));
1208
+ const ElementClass = owner && owner.defaultView ? owner.defaultView.HTMLElement : HTMLElement;
1209
+ return value instanceof ElementClass;
1215
1210
  };
1216
1211
 
1217
1212
  var isMultipleSelect = (element) => element.type === `select-multiple`;
@@ -1321,7 +1316,7 @@ var getResolverOptions = (fieldsNames, _fields, criteriaMode, shouldUseNativeVal
1321
1316
  };
1322
1317
 
1323
1318
  var getRuleValue = (rule) => isUndefined(rule)
1324
- ? undefined
1319
+ ? rule
1325
1320
  : isRegex(rule)
1326
1321
  ? rule.source
1327
1322
  : isObject(rule)
@@ -1409,9 +1404,7 @@ function createFormControl(props = {}) {
1409
1404
  errors: {},
1410
1405
  };
1411
1406
  let _fields = {};
1412
- let _defaultValues = isObject(_options.defaultValues)
1413
- ? cloneObject(_options.defaultValues) || {}
1414
- : {};
1407
+ let _defaultValues = cloneObject(_options.defaultValues) || {};
1415
1408
  let _formValues = _options.shouldUnregister
1416
1409
  ? {}
1417
1410
  : cloneObject(_defaultValues);
@@ -1428,7 +1421,6 @@ function createFormControl(props = {}) {
1428
1421
  };
1429
1422
  let delayErrorCallback;
1430
1423
  let timer = 0;
1431
- let validateFields = {};
1432
1424
  const _proxyFormState = {
1433
1425
  isDirty: false,
1434
1426
  dirtyFields: false,
@@ -1450,9 +1442,8 @@ function createFormControl(props = {}) {
1450
1442
  timer = window.setTimeout(callback, wait);
1451
1443
  };
1452
1444
  const _updateValid = async () => {
1453
- let isValid = false;
1454
1445
  if (_proxyFormState.isValid) {
1455
- isValid = _options.resolver
1446
+ const isValid = _options.resolver
1456
1447
  ? isEmptyObject((await _executeSchema()).errors)
1457
1448
  : await executeBuiltInValidation(_fields, true);
1458
1449
  if (isValid !== _formState.isValid) {
@@ -1462,8 +1453,12 @@ function createFormControl(props = {}) {
1462
1453
  });
1463
1454
  }
1464
1455
  }
1465
- return isValid;
1466
1456
  };
1457
+ const _updateIsValidating = (value) => _proxyFormState.isValidating &&
1458
+ value !== _formState.isValidating &&
1459
+ _subjects.state.next({
1460
+ isValidating: value,
1461
+ });
1467
1462
  const _updateFieldArray = (name, values = [], method, args, shouldSetValues = true, shouldUpdateFieldsAndState = true) => {
1468
1463
  if (args && method) {
1469
1464
  _stateFlags.action = true;
@@ -1471,8 +1466,7 @@ function createFormControl(props = {}) {
1471
1466
  const fieldValues = method(get(_fields, name), args.argA, args.argB);
1472
1467
  shouldSetValues && set(_fields, name, fieldValues);
1473
1468
  }
1474
- if (_proxyFormState.errors &&
1475
- shouldUpdateFieldsAndState &&
1469
+ if (shouldUpdateFieldsAndState &&
1476
1470
  Array.isArray(get(_formState.errors, name))) {
1477
1471
  const errors = method(get(_formState.errors, name), args.argA, args.argB);
1478
1472
  shouldSetValues && set(_formState.errors, name, errors);
@@ -1488,6 +1482,7 @@ function createFormControl(props = {}) {
1488
1482
  _formState.dirtyFields = getDirtyFields(_defaultValues, _formValues);
1489
1483
  }
1490
1484
  _subjects.state.next({
1485
+ name,
1491
1486
  isDirty: _getDirty(name, values),
1492
1487
  dirtyFields: _formState.dirtyFields,
1493
1488
  errors: _formState.errors,
@@ -1522,20 +1517,22 @@ function createFormControl(props = {}) {
1522
1517
  const output = {
1523
1518
  name,
1524
1519
  };
1525
- if (_proxyFormState.isDirty) {
1526
- isPreviousDirty = _formState.isDirty;
1527
- _formState.isDirty = output.isDirty = _getDirty();
1528
- shouldUpdateField = isPreviousDirty !== output.isDirty;
1529
- }
1530
- if (_proxyFormState.dirtyFields && (!isBlurEvent || shouldDirty)) {
1531
- isPreviousDirty = get(_formState.dirtyFields, name);
1532
- const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
1533
- isCurrentFieldPristine
1534
- ? unset(_formState.dirtyFields, name)
1535
- : set(_formState.dirtyFields, name, true);
1536
- output.dirtyFields = _formState.dirtyFields;
1537
- shouldUpdateField =
1538
- shouldUpdateField || isPreviousDirty !== !isCurrentFieldPristine;
1520
+ if (!isBlurEvent || shouldDirty) {
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
+ }
1539
1536
  }
1540
1537
  if (isBlurEvent) {
1541
1538
  const isPreviousFieldTouched = get(_formState.touchedFields, name);
@@ -1582,18 +1579,9 @@ function createFormControl(props = {}) {
1582
1579
  };
1583
1580
  _subjects.state.next(updatedFormState);
1584
1581
  }
1585
- validateFields[name]--;
1586
- if (_proxyFormState.isValidating &&
1587
- !Object.values(validateFields).some((v) => v)) {
1588
- _subjects.state.next({
1589
- isValidating: false,
1590
- });
1591
- validateFields = {};
1592
- }
1582
+ _updateIsValidating(false);
1593
1583
  };
1594
- const _executeSchema = async (name) => _options.resolver
1595
- ? await _options.resolver({ ..._formValues }, _options.context, getResolverOptions(name || _names.mount, _fields, _options.criteriaMode, _options.shouldUseNativeValidation))
1596
- : {};
1584
+ const _executeSchema = async (name) => await _options.resolver(_formValues, _options.context, getResolverOptions(name || _names.mount, _fields, _options.criteriaMode, _options.shouldUseNativeValidation));
1597
1585
  const executeSchemaAndUpdateState = async (names) => {
1598
1586
  const { errors } = await _executeSchema();
1599
1587
  if (names) {
@@ -1651,18 +1639,15 @@ function createFormControl(props = {}) {
1651
1639
  };
1652
1640
  const _getDirty = (name, data) => (name && data && set(_formValues, name, data),
1653
1641
  !deepEqual(getValues(), _defaultValues));
1654
- const _getWatch = (names, defaultValue, isGlobal) => {
1655
- const fieldValues = {
1656
- ...(_stateFlags.mount
1657
- ? _formValues
1658
- : isUndefined(defaultValue)
1659
- ? _defaultValues
1660
- : isString(names)
1661
- ? { [names]: defaultValue }
1662
- : defaultValue),
1663
- };
1664
- return generateWatchOutput(names, _names, fieldValues, isGlobal);
1665
- };
1642
+ const _getWatch = (names, defaultValue, isGlobal) => generateWatchOutput(names, _names, {
1643
+ ...(_stateFlags.mount
1644
+ ? _formValues
1645
+ : isUndefined(defaultValue)
1646
+ ? _defaultValues
1647
+ : isString(names)
1648
+ ? { [names]: defaultValue }
1649
+ : defaultValue),
1650
+ }, isGlobal);
1666
1651
  const _getFieldArray = (name) => compact(get(_stateFlags.mount ? _formValues : _defaultValues, name, props.shouldUnregister ? get(_defaultValues, name, []) : []));
1667
1652
  const setFieldValue = (name, value, options = {}) => {
1668
1653
  const field = get(_fields, name);
@@ -1757,12 +1742,11 @@ function createFormControl(props = {}) {
1757
1742
  const target = event.target;
1758
1743
  let name = target.name;
1759
1744
  const field = get(_fields, name);
1745
+ const getCurrentFieldValue = () => target.type ? getFieldValue(field._f) : getEventValue(event);
1760
1746
  if (field) {
1761
1747
  let error;
1762
1748
  let isValid;
1763
- const fieldValue = target.type
1764
- ? getFieldValue(field._f)
1765
- : getEventValue(event);
1749
+ const fieldValue = getCurrentFieldValue();
1766
1750
  const isBlurEvent = event.type === EVENTS.BLUR || event.type === EVENTS.FOCUS_OUT;
1767
1751
  const shouldSkipValidation = (!hasValidation(field._f) &&
1768
1752
  !_options.resolver &&
@@ -1791,12 +1775,7 @@ function createFormControl(props = {}) {
1791
1775
  _subjects.state.next({ name, ...(watched ? {} : fieldState) }));
1792
1776
  }
1793
1777
  !isBlurEvent && watched && _subjects.state.next({});
1794
- validateFields[name] = validateFields[name]
1795
- ? validateFields[name] + 1
1796
- : 1;
1797
- _subjects.state.next({
1798
- isValidating: true,
1799
- });
1778
+ _updateIsValidating(true);
1800
1779
  if (_options.resolver) {
1801
1780
  const { errors } = await _executeSchema([name]);
1802
1781
  const previousErrorLookupResult = schemaErrorLookup(_formState.errors, _fields, name);
@@ -1807,20 +1786,28 @@ function createFormControl(props = {}) {
1807
1786
  }
1808
1787
  else {
1809
1788
  error = (await validateField(field, get(_formValues, name), shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation))[name];
1810
- _updateValid();
1789
+ if (error) {
1790
+ isValid = false;
1791
+ }
1792
+ else if (_proxyFormState.isValid) {
1793
+ isValid = await executeBuiltInValidation(_fields, true);
1794
+ }
1795
+ }
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);
1811
1803
  }
1812
- field._f.deps &&
1813
- trigger(field._f.deps);
1814
- shouldRenderByError(name, isValid, error, fieldState);
1815
1804
  }
1816
1805
  };
1817
1806
  const trigger = async (name, options = {}) => {
1818
1807
  let isValid;
1819
1808
  let validationResult;
1820
1809
  const fieldNames = convertToArrayPayload(name);
1821
- _subjects.state.next({
1822
- isValidating: true,
1823
- });
1810
+ _updateIsValidating(true);
1824
1811
  if (_options.resolver) {
1825
1812
  const errors = await executeSchemaAndUpdateState(isUndefined(name) ? name : fieldNames);
1826
1813
  isValid = isEmptyObject(errors);
@@ -1892,7 +1879,7 @@ function createFormControl(props = {}) {
1892
1879
  };
1893
1880
  const watch = (name, defaultValue) => isFunction(name)
1894
1881
  ? _subjects.watch.subscribe({
1895
- next: (info) => name(_getWatch(undefined, defaultValue), info),
1882
+ next: (payload) => name(_getWatch(undefined, defaultValue), payload),
1896
1883
  })
1897
1884
  : _getWatch(name, defaultValue, true);
1898
1885
  const unregister = (name, options = {}) => {
@@ -1977,9 +1964,7 @@ function createFormControl(props = {}) {
1977
1964
  refs: [
1978
1965
  ...refs.filter(live),
1979
1966
  fieldRef,
1980
- ...(!!Array.isArray(get(_defaultValues, name))
1981
- ? [{}]
1982
- : []),
1967
+ ...(Array.isArray(get(_defaultValues, name)) ? [{}] : []),
1983
1968
  ],
1984
1969
  ref: { type: fieldRef.type, name },
1985
1970
  }
@@ -2175,11 +2160,6 @@ function createFormControl(props = {}) {
2175
2160
  }
2176
2161
  }
2177
2162
  };
2178
- if (isFunction(_options.defaultValues)) {
2179
- _options.defaultValues().then((values) => {
2180
- reset(values, _options.resetOptions);
2181
- });
2182
- }
2183
2163
  return {
2184
2164
  control: {
2185
2165
  register,
@@ -2193,7 +2173,6 @@ function createFormControl(props = {}) {
2193
2173
  _removeUnmounted,
2194
2174
  _updateFieldArray,
2195
2175
  _getFieldArray,
2196
- _reset,
2197
2176
  _subjects,
2198
2177
  _proxyFormState,
2199
2178
  get _fields() {
@@ -2291,9 +2270,7 @@ function useForm(props = {}) {
2291
2270
  dirtyFields: {},
2292
2271
  touchedFields: {},
2293
2272
  errors: {},
2294
- defaultValues: isFunction(props.defaultValues)
2295
- ? undefined
2296
- : props.defaultValues,
2273
+ defaultValues: props.defaultValues,
2297
2274
  });
2298
2275
  if (!_formControl.current) {
2299
2276
  _formControl.current = {
@@ -2305,7 +2282,7 @@ function useForm(props = {}) {
2305
2282
  control._options = props;
2306
2283
  useSubscribe({
2307
2284
  subject: control._subjects.state,
2308
- next: (value) => {
2285
+ callback: React.useCallback((value) => {
2309
2286
  if (shouldRenderFormState(value, control._proxyFormState, true)) {
2310
2287
  control._formState = {
2311
2288
  ...control._formState,
@@ -2313,7 +2290,7 @@ function useForm(props = {}) {
2313
2290
  };
2314
2291
  updateFormState({ ...control._formState });
2315
2292
  }
2316
- },
2293
+ }, [control]),
2317
2294
  });
2318
2295
  React.useEffect(() => {
2319
2296
  if (!control._stateFlags.mount) {
@@ -2326,11 +2303,6 @@ function useForm(props = {}) {
2326
2303
  }
2327
2304
  control._removeUnmounted();
2328
2305
  });
2329
- React.useEffect(() => {
2330
- if (props.values && !deepEqual(props.values, control._defaultValues)) {
2331
- control._reset(props.values, control._options.resetOptions);
2332
- }
2333
- }, [props.values, control]);
2334
2306
  React.useEffect(() => {
2335
2307
  formState.submitCount && control._focusError();
2336
2308
  }, [control, formState.submitCount]);