react-hook-form 7.57.0-next.0 → 7.57.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.
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import React__default, { useEffect } from 'react';
2
+ import React__default from 'react';
3
3
 
4
4
  var isCheckBoxInput = (element) => element.type === 'checkbox';
5
5
 
@@ -217,47 +217,7 @@ var getProxyFormState = (formState, control, localProxyFormState, isRoot = true)
217
217
  return result;
218
218
  };
219
219
 
220
- var isPrimitive = (value) => isNullOrUndefined(value) || !isObjectType(value);
221
-
222
- function deepEqual(object1, object2) {
223
- if (isPrimitive(object1) || isPrimitive(object2)) {
224
- return object1 === object2;
225
- }
226
- if (isDateObject(object1) && isDateObject(object2)) {
227
- return object1.getTime() === object2.getTime();
228
- }
229
- const keys1 = Object.keys(object1);
230
- const keys2 = Object.keys(object2);
231
- if (keys1.length !== keys2.length) {
232
- return false;
233
- }
234
- for (const key of keys1) {
235
- const val1 = object1[key];
236
- if (!keys2.includes(key)) {
237
- return false;
238
- }
239
- if (key !== 'ref') {
240
- const val2 = object2[key];
241
- if ((isDateObject(val1) && isDateObject(val2)) ||
242
- (isObject(val1) && isObject(val2)) ||
243
- (Array.isArray(val1) && Array.isArray(val2))
244
- ? !deepEqual(val1, val2)
245
- : val1 !== val2) {
246
- return false;
247
- }
248
- }
249
- }
250
- return true;
251
- }
252
-
253
- const useDeepEqualEffect = (effect, deps) => {
254
- const ref = React.useRef(deps);
255
- if (!deepEqual(deps, ref.current)) {
256
- ref.current = deps;
257
- }
258
- // eslint-disable-next-line react-hooks/exhaustive-deps
259
- React.useEffect(effect, ref.current);
260
- };
220
+ const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
261
221
 
262
222
  /**
263
223
  * This custom hook allows you to subscribe to each form state, and isolate the re-render at the custom hook level. It has its scope in terms of form state subscription, so it would not affect other useFormState and useForm. Using this hook can reduce the re-render impact on large and complex form application.
@@ -303,8 +263,8 @@ function useFormState(props) {
303
263
  isValid: false,
304
264
  errors: false,
305
265
  });
306
- useDeepEqualEffect(() => control._subscribe({
307
- name: name,
266
+ useIsomorphicLayoutEffect(() => control._subscribe({
267
+ name,
308
268
  formState: _localProxyFormState.current,
309
269
  exact,
310
270
  callback: (formState) => {
@@ -353,34 +313,18 @@ var generateWatchOutput = (names, _names, formValues, isGlobal, defaultValue) =>
353
313
  */
354
314
  function useWatch(props) {
355
315
  const methods = useFormContext();
356
- const { control = methods.control, name, defaultValue, disabled, exact, compute, } = props || {};
357
- const _compute = React__default.useRef(compute);
358
- const _computeFormValues = React__default.useRef(undefined);
359
- _compute.current = compute;
360
- const defaultValueMemo = React__default.useMemo(() => control._getWatch(name, defaultValue), [control, name, defaultValue]);
361
- const [value, updateValue] = React__default.useState(_compute.current ? _compute.current(defaultValueMemo) : defaultValueMemo);
362
- useDeepEqualEffect(() => control._subscribe({
363
- name: name,
316
+ const { control = methods.control, name, defaultValue, disabled, exact, } = props || {};
317
+ const _defaultValue = React__default.useRef(defaultValue);
318
+ const [value, updateValue] = React__default.useState(control._getWatch(name, _defaultValue.current));
319
+ useIsomorphicLayoutEffect(() => control._subscribe({
320
+ name,
364
321
  formState: {
365
322
  values: true,
366
323
  },
367
324
  exact,
368
- callback: (formState) => {
369
- if (!disabled) {
370
- const formValues = generateWatchOutput(name, control._names, formState.values || control._formValues, false, defaultValue);
371
- if (_compute.current) {
372
- const computedFormValues = _compute.current(formValues);
373
- if (!deepEqual(computedFormValues, _computeFormValues.current)) {
374
- updateValue(computedFormValues);
375
- _computeFormValues.current = computedFormValues;
376
- }
377
- }
378
- else {
379
- updateValue(formValues);
380
- }
381
- }
382
- },
383
- }), [defaultValue, disabled, name, exact]);
325
+ callback: (formState) => !disabled &&
326
+ updateValue(generateWatchOutput(name, control._names, formState.values || control._formValues, false, _defaultValue.current)),
327
+ }), [name, control, disabled, exact]);
384
328
  React__default.useEffect(() => control._removeUnmounted());
385
329
  return value;
386
330
  }
@@ -411,13 +355,12 @@ function useWatch(props) {
411
355
  */
412
356
  function useController(props) {
413
357
  const methods = useFormContext();
414
- const { name, disabled, control = methods.control, shouldUnregister, defaultValue, } = props;
358
+ const { name, disabled, control = methods.control, shouldUnregister } = props;
415
359
  const isArrayField = isNameInFieldArray(control._names.array, name);
416
- const defaultValueMemo = React__default.useMemo(() => get(control._formValues, name, get(control._defaultValues, name, defaultValue)), [control, name, defaultValue]);
417
360
  const value = useWatch({
418
361
  control,
419
362
  name,
420
- defaultValue: defaultValueMemo,
363
+ defaultValue: get(control._formValues, name, get(control._defaultValues, name, props.defaultValue)),
421
364
  exact: true,
422
365
  });
423
366
  const formState = useFormState({
@@ -431,7 +374,6 @@ function useController(props) {
431
374
  value,
432
375
  ...(isBoolean(props.disabled) ? { disabled: props.disabled } : {}),
433
376
  }));
434
- _props.current = props;
435
377
  const fieldState = React__default.useMemo(() => Object.defineProperties({}, {
436
378
  invalid: {
437
379
  enumerable: true,
@@ -471,7 +413,12 @@ function useController(props) {
471
413
  const ref = React__default.useCallback((elm) => {
472
414
  const field = get(control._fields, name);
473
415
  if (field && elm) {
474
- field._f.ref = elm;
416
+ field._f.ref = {
417
+ focus: () => elm.focus && elm.focus(),
418
+ select: () => elm.select && elm.select(),
419
+ setCustomValidity: (message) => elm.setCustomValidity(message),
420
+ reportValidity: () => elm.reportValidity(),
421
+ };
475
422
  }
476
423
  }, [control._fields, name]);
477
424
  const field = React__default.useMemo(() => ({
@@ -727,6 +674,39 @@ var createSubject = () => {
727
674
  };
728
675
  };
729
676
 
677
+ var isPrimitive = (value) => isNullOrUndefined(value) || !isObjectType(value);
678
+
679
+ function deepEqual(object1, object2) {
680
+ if (isPrimitive(object1) || isPrimitive(object2)) {
681
+ return object1 === object2;
682
+ }
683
+ if (isDateObject(object1) && isDateObject(object2)) {
684
+ return object1.getTime() === object2.getTime();
685
+ }
686
+ const keys1 = Object.keys(object1);
687
+ const keys2 = Object.keys(object2);
688
+ if (keys1.length !== keys2.length) {
689
+ return false;
690
+ }
691
+ for (const key of keys1) {
692
+ const val1 = object1[key];
693
+ if (!keys2.includes(key)) {
694
+ return false;
695
+ }
696
+ if (key !== 'ref') {
697
+ const val2 = object2[key];
698
+ if ((isDateObject(val1) && isDateObject(val2)) ||
699
+ (isObject(val1) && isObject(val2)) ||
700
+ (Array.isArray(val1) && Array.isArray(val2))
701
+ ? !deepEqual(val1, val2)
702
+ : val1 !== val2) {
703
+ return false;
704
+ }
705
+ }
706
+ }
707
+ return true;
708
+ }
709
+
730
710
  var isEmptyObject = (value) => isObject(value) && !Object.keys(value).length;
731
711
 
732
712
  var isFileInput = (element) => element.type === 'file';
@@ -1012,6 +992,12 @@ function schemaErrorLookup(errors, _fields, name) {
1012
992
  error: foundError,
1013
993
  };
1014
994
  }
995
+ if (foundError && foundError.root && foundError.root.type) {
996
+ return {
997
+ name: `${fieldName}.root`,
998
+ error: foundError.root,
999
+ };
1000
+ }
1015
1001
  names.pop();
1016
1002
  }
1017
1003
  return {
@@ -1290,7 +1276,7 @@ function createFormControl(props = {}) {
1290
1276
  };
1291
1277
  const _fields = {};
1292
1278
  let _defaultValues = isObject(_options.defaultValues) || isObject(_options.values)
1293
- ? cloneObject(_options.values || _options.defaultValues) || {}
1279
+ ? cloneObject(_options.defaultValues || _options.values) || {}
1294
1280
  : {};
1295
1281
  let _formValues = _options.shouldUnregister
1296
1282
  ? {}
@@ -1325,8 +1311,6 @@ function createFormControl(props = {}) {
1325
1311
  array: createSubject(),
1326
1312
  state: createSubject(),
1327
1313
  };
1328
- const validationModeBeforeSubmit = getValidationModes(_options.mode);
1329
- const validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
1330
1314
  const shouldDisplayAllAssociatedErrors = _options.criteriaMode === VALIDATION_MODE.all;
1331
1315
  const debounce = (callback) => (wait) => {
1332
1316
  clearTimeout(timer);
@@ -1597,13 +1581,17 @@ function createFormControl(props = {}) {
1597
1581
  }
1598
1582
  else if (fieldReference.refs) {
1599
1583
  if (isCheckBoxInput(fieldReference.ref)) {
1600
- fieldReference.refs.length > 1
1601
- ? fieldReference.refs.forEach((checkboxRef) => (!checkboxRef.defaultChecked || !checkboxRef.disabled) &&
1602
- (checkboxRef.checked = Array.isArray(fieldValue)
1603
- ? !!fieldValue.find((data) => data === checkboxRef.value)
1604
- : fieldValue === checkboxRef.value))
1605
- : fieldReference.refs[0] &&
1606
- (fieldReference.refs[0].checked = !!fieldValue);
1584
+ fieldReference.refs.forEach((checkboxRef) => {
1585
+ if (!checkboxRef.defaultChecked || !checkboxRef.disabled) {
1586
+ if (Array.isArray(fieldValue)) {
1587
+ checkboxRef.checked = !!fieldValue.find((data) => data === checkboxRef.value);
1588
+ }
1589
+ else {
1590
+ checkboxRef.checked =
1591
+ fieldValue === checkboxRef.value || !!fieldValue;
1592
+ }
1593
+ }
1594
+ });
1607
1595
  }
1608
1596
  else {
1609
1597
  fieldReference.refs.forEach((radioRef) => (radioRef.checked = radioRef.value === fieldValue));
@@ -1629,8 +1617,11 @@ function createFormControl(props = {}) {
1629
1617
  };
1630
1618
  const setValues = (name, value, options) => {
1631
1619
  for (const fieldKey in value) {
1620
+ if (!value.hasOwnProperty(fieldKey)) {
1621
+ return;
1622
+ }
1632
1623
  const fieldValue = value[fieldKey];
1633
- const fieldName = `${name}.${fieldKey}`;
1624
+ const fieldName = name + '.' + fieldKey;
1634
1625
  const field = get(_fields, fieldName);
1635
1626
  (_names.array.has(name) ||
1636
1627
  isObject(fieldValue) ||
@@ -1685,6 +1676,8 @@ function createFormControl(props = {}) {
1685
1676
  (isDateObject(fieldValue) && isNaN(fieldValue.getTime())) ||
1686
1677
  deepEqual(fieldValue, get(_formValues, name, fieldValue));
1687
1678
  };
1679
+ const validationModeBeforeSubmit = getValidationModes(_options.mode);
1680
+ const validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
1688
1681
  if (field) {
1689
1682
  let error;
1690
1683
  let isValid;
@@ -2227,6 +2220,7 @@ function createFormControl(props = {}) {
2227
2220
  setError,
2228
2221
  _subscribe,
2229
2222
  _runSchema,
2223
+ _focusError,
2230
2224
  _getWatch,
2231
2225
  _getDirty,
2232
2226
  _setValid,
@@ -2404,22 +2398,24 @@ function useFieldArray(props) {
2404
2398
  const [fields, setFields] = React__default.useState(control._getFieldArray(name));
2405
2399
  const ids = React__default.useRef(control._getFieldArray(name).map(generateId));
2406
2400
  const _fieldIds = React__default.useRef(fields);
2401
+ const _name = React__default.useRef(name);
2407
2402
  const _actioned = React__default.useRef(false);
2403
+ _name.current = name;
2408
2404
  _fieldIds.current = fields;
2409
2405
  control._names.array.add(name);
2410
- React__default.useMemo(() => rules &&
2411
- control.register(name, rules), [control, rules, name]);
2412
- useEffect(() => control._subjects.array.subscribe({
2406
+ rules &&
2407
+ control.register(name, rules);
2408
+ React__default.useEffect(() => control._subjects.array.subscribe({
2413
2409
  next: ({ values, name: fieldArrayName, }) => {
2414
- if (fieldArrayName === name || !fieldArrayName) {
2415
- const fieldValues = get(values, name);
2410
+ if (fieldArrayName === _name.current || !fieldArrayName) {
2411
+ const fieldValues = get(values, _name.current);
2416
2412
  if (Array.isArray(fieldValues)) {
2417
2413
  setFields(fieldValues);
2418
2414
  ids.current = fieldValues.map(generateId);
2419
2415
  }
2420
2416
  }
2421
2417
  },
2422
- }).unsubscribe, [control, name]);
2418
+ }).unsubscribe, [control]);
2423
2419
  const updateValues = React__default.useCallback((updatedFieldArrayValues) => {
2424
2420
  _actioned.current = true;
2425
2421
  control._setFieldArray(name, updatedFieldArrayValues);
@@ -2599,7 +2595,6 @@ function useFieldArray(props) {
2599
2595
  };
2600
2596
  }
2601
2597
 
2602
- const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? React__default.useLayoutEffect : React__default.useEffect;
2603
2598
  /**
2604
2599
  * Custom hook to manage the entire form.
2605
2600
  *
@@ -2685,10 +2680,13 @@ function useForm(props = {}) {
2685
2680
  if (props.reValidateMode) {
2686
2681
  control._options.reValidateMode = props.reValidateMode;
2687
2682
  }
2688
- if (props.errors && !isEmptyObject(props.errors)) {
2683
+ }, [control, props.mode, props.reValidateMode]);
2684
+ React__default.useEffect(() => {
2685
+ if (props.errors) {
2689
2686
  control._setErrors(props.errors);
2687
+ control._focusError();
2690
2688
  }
2691
- }, [control, props.errors, props.mode, props.reValidateMode]);
2689
+ }, [control, props.errors]);
2692
2690
  React__default.useEffect(() => {
2693
2691
  props.shouldUnregister &&
2694
2692
  control._subjects.state.next({