react-hook-form 7.53.2 → 7.54.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.
@@ -34,13 +34,14 @@ var isWeb = typeof window !== 'undefined' &&
34
34
  function cloneObject(data) {
35
35
  let copy;
36
36
  const isArray = Array.isArray(data);
37
+ const isFileListInstance = typeof FileList !== 'undefined' ? data instanceof FileList : false;
37
38
  if (data instanceof Date) {
38
39
  copy = new Date(data);
39
40
  }
40
41
  else if (data instanceof Set) {
41
42
  copy = new Set(data);
42
43
  }
43
- else if (!(isWeb && (data instanceof Blob || data instanceof FileList)) &&
44
+ else if (!(isWeb && (data instanceof Blob || isFileListInstance)) &&
44
45
  (isArray || isObject(data))) {
45
46
  copy = isArray ? [] : {};
46
47
  if (!isArray && !isPlainObject(data)) {
@@ -99,7 +100,7 @@ var set = (object, path, value) => {
99
100
  ? []
100
101
  : {};
101
102
  }
102
- if (key === '__proto__') {
103
+ if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
103
104
  return;
104
105
  }
105
106
  object[key] = newValue;
@@ -318,7 +319,7 @@ function useFormState(props) {
318
319
  _mounted.current = false;
319
320
  };
320
321
  }, [control]);
321
- return getProxyFormState(formState, control, _localProxyFormState.current, false);
322
+ return React.useMemo(() => getProxyFormState(formState, control, _localProxyFormState.current, false), [formState, control]);
322
323
  }
323
324
 
324
325
  var isString = (value) => typeof value === 'string';
@@ -414,6 +415,67 @@ function useController(props) {
414
415
  value,
415
416
  ...(isBoolean(props.disabled) ? { disabled: props.disabled } : {}),
416
417
  }));
418
+ const fieldState = React.useMemo(() => Object.defineProperties({}, {
419
+ invalid: {
420
+ enumerable: true,
421
+ get: () => !!get(formState.errors, name),
422
+ },
423
+ isDirty: {
424
+ enumerable: true,
425
+ get: () => !!get(formState.dirtyFields, name),
426
+ },
427
+ isTouched: {
428
+ enumerable: true,
429
+ get: () => !!get(formState.touchedFields, name),
430
+ },
431
+ isValidating: {
432
+ enumerable: true,
433
+ get: () => !!get(formState.validatingFields, name),
434
+ },
435
+ error: {
436
+ enumerable: true,
437
+ get: () => get(formState.errors, name),
438
+ },
439
+ }), [formState, name]);
440
+ const field = React.useMemo(() => ({
441
+ name,
442
+ value,
443
+ ...(isBoolean(disabled) || formState.disabled
444
+ ? { disabled: formState.disabled || disabled }
445
+ : {}),
446
+ onChange: (event) => _registerProps.current.onChange({
447
+ target: {
448
+ value: getEventValue(event),
449
+ name: name,
450
+ },
451
+ type: EVENTS.CHANGE,
452
+ }),
453
+ onBlur: () => _registerProps.current.onBlur({
454
+ target: {
455
+ value: get(control._formValues, name),
456
+ name: name,
457
+ },
458
+ type: EVENTS.BLUR,
459
+ }),
460
+ ref: (elm) => {
461
+ const field = get(control._fields, name);
462
+ if (field && elm) {
463
+ field._f.ref = {
464
+ focus: () => elm.focus(),
465
+ select: () => elm.select(),
466
+ setCustomValidity: (message) => elm.setCustomValidity(message),
467
+ reportValidity: () => elm.reportValidity(),
468
+ };
469
+ }
470
+ },
471
+ }), [
472
+ name,
473
+ control._formValues,
474
+ disabled,
475
+ formState.disabled,
476
+ value,
477
+ control._fields,
478
+ ]);
417
479
  React.useEffect(() => {
418
480
  const _shouldUnregisterField = control._options.shouldUnregister || shouldUnregister;
419
481
  const updateMounted = (name, value) => {
@@ -439,7 +501,7 @@ function useController(props) {
439
501
  };
440
502
  }, [name, control, isArrayField, shouldUnregister]);
441
503
  React.useEffect(() => {
442
- if (get(control._fields, name)) {
504
+ if (isBoolean(disabled) && get(control._fields, name)) {
443
505
  control._updateDisabledField({
444
506
  disabled,
445
507
  fields: control._fields,
@@ -448,63 +510,11 @@ function useController(props) {
448
510
  });
449
511
  }
450
512
  }, [disabled, name, control]);
451
- return {
452
- field: {
453
- name,
454
- value,
455
- ...(isBoolean(disabled) || formState.disabled
456
- ? { disabled: formState.disabled || disabled }
457
- : {}),
458
- onChange: React.useCallback((event) => _registerProps.current.onChange({
459
- target: {
460
- value: getEventValue(event),
461
- name: name,
462
- },
463
- type: EVENTS.CHANGE,
464
- }), [name]),
465
- onBlur: React.useCallback(() => _registerProps.current.onBlur({
466
- target: {
467
- value: get(control._formValues, name),
468
- name: name,
469
- },
470
- type: EVENTS.BLUR,
471
- }), [name, control]),
472
- ref: React.useCallback((elm) => {
473
- const field = get(control._fields, name);
474
- if (field && elm) {
475
- field._f.ref = {
476
- focus: () => elm.focus(),
477
- select: () => elm.select(),
478
- setCustomValidity: (message) => elm.setCustomValidity(message),
479
- reportValidity: () => elm.reportValidity(),
480
- };
481
- }
482
- }, [control._fields, name]),
483
- },
513
+ return React.useMemo(() => ({
514
+ field,
484
515
  formState,
485
- fieldState: Object.defineProperties({}, {
486
- invalid: {
487
- enumerable: true,
488
- get: () => !!get(formState.errors, name),
489
- },
490
- isDirty: {
491
- enumerable: true,
492
- get: () => !!get(formState.dirtyFields, name),
493
- },
494
- isTouched: {
495
- enumerable: true,
496
- get: () => !!get(formState.touchedFields, name),
497
- },
498
- isValidating: {
499
- enumerable: true,
500
- get: () => !!get(formState.validatingFields, name),
501
- },
502
- error: {
503
- enumerable: true,
504
- get: () => get(formState.errors, name),
505
- },
506
- }),
507
- };
516
+ fieldState,
517
+ }), [field, formState, fieldState]);
508
518
  }
509
519
 
510
520
  /**
@@ -554,7 +564,7 @@ const Controller = (props) => props.render(useController(props));
554
564
  const flatten = (obj) => {
555
565
  const output = {};
556
566
  for (const key of Object.keys(obj)) {
557
- if (isObjectType(obj[key])) {
567
+ if (isObjectType(obj[key]) && obj[key] !== null) {
558
568
  const nested = flatten(obj[key]);
559
569
  for (const nestedKey of Object.keys(nested)) {
560
570
  output[`${key}.${nestedKey}`] = nested[nestedKey];
@@ -1121,7 +1131,7 @@ var updateAt = (fieldValues, index, value) => {
1121
1131
  */
1122
1132
  function useFieldArray(props) {
1123
1133
  const methods = useFormContext();
1124
- const { control = methods.control, name, keyName = 'id', shouldUnregister, } = props;
1134
+ const { control = methods.control, name, keyName = 'id', shouldUnregister, rules, } = props;
1125
1135
  const [fields, setFields] = React.useState(control._getFieldArray(name));
1126
1136
  const ids = React.useRef(control._getFieldArray(name).map(generateId));
1127
1137
  const _fieldIds = React.useRef(fields);
@@ -1130,8 +1140,8 @@ function useFieldArray(props) {
1130
1140
  _name.current = name;
1131
1141
  _fieldIds.current = fields;
1132
1142
  control._names.array.add(name);
1133
- props.rules &&
1134
- control.register(name, props.rules);
1143
+ rules &&
1144
+ control.register(name, rules);
1135
1145
  useSubscribe({
1136
1146
  next: ({ values, name: fieldArrayName, }) => {
1137
1147
  if (fieldArrayName === _name.current || !fieldArrayName) {
@@ -1175,6 +1185,8 @@ function useFieldArray(props) {
1175
1185
  ids.current = removeArrayAt(ids.current, index);
1176
1186
  updateValues(updatedFieldArrayValues);
1177
1187
  setFields(updatedFieldArrayValues);
1188
+ !Array.isArray(get(control._fields, name)) &&
1189
+ set(control._fields, name, undefined);
1178
1190
  control._updateFieldArray(name, updatedFieldArrayValues, removeArrayAt, {
1179
1191
  argA: index,
1180
1192
  });
@@ -1489,7 +1501,8 @@ var getRuleValue = (rule) => isUndefined(rule)
1489
1501
  : rule;
1490
1502
 
1491
1503
  const ASYNC_FUNCTION = 'AsyncFunction';
1492
- var hasPromiseValidation = (fieldReference) => (!fieldReference || !fieldReference.validate) &&
1504
+ var hasPromiseValidation = (fieldReference) => !!fieldReference &&
1505
+ !!fieldReference.validate &&
1493
1506
  !!((isFunction(fieldReference.validate) &&
1494
1507
  fieldReference.validate.constructor.name === ASYNC_FUNCTION) ||
1495
1508
  (isObject(fieldReference.validate) &&
@@ -1751,9 +1764,9 @@ function createFormControl(props = {}) {
1751
1764
  const shouldUpdateValid = _proxyFormState.isValid &&
1752
1765
  isBoolean(isValid) &&
1753
1766
  _formState.isValid !== isValid;
1754
- if (props.delayError && error) {
1767
+ if (_options.delayError && error) {
1755
1768
  delayErrorCallback = debounce(() => updateErrors(name, error));
1756
- delayErrorCallback(props.delayError);
1769
+ delayErrorCallback(_options.delayError);
1757
1770
  }
1758
1771
  else {
1759
1772
  clearTimeout(timer);
@@ -1858,7 +1871,7 @@ function createFormControl(props = {}) {
1858
1871
  ? { [names]: defaultValue }
1859
1872
  : defaultValue),
1860
1873
  }, isGlobal, defaultValue);
1861
- const _getFieldArray = (name) => compact(get(_state.mount ? _formValues : _defaultValues, name, props.shouldUnregister ? get(_defaultValues, name, []) : []));
1874
+ const _getFieldArray = (name) => compact(get(_state.mount ? _formValues : _defaultValues, name, _options.shouldUnregister ? get(_defaultValues, name, []) : []));
1862
1875
  const setFieldValue = (name, value, options = {}) => {
1863
1876
  const field = get(_fields, name);
1864
1877
  let fieldValue = value;
@@ -1991,7 +2004,7 @@ function createFormControl(props = {}) {
1991
2004
  });
1992
2005
  if (shouldSkipValidation) {
1993
2006
  if (_proxyFormState.isValid) {
1994
- if (props.mode === 'onBlur') {
2007
+ if (_options.mode === 'onBlur') {
1995
2008
  if (isBlurEvent) {
1996
2009
  _updateValid();
1997
2010
  }
@@ -2156,7 +2169,9 @@ function createFormControl(props = {}) {
2156
2169
  : isUndefined(value)
2157
2170
  ? getFieldValue(field ? field._f : get(fields, name)._f)
2158
2171
  : value;
2159
- set(_formValues, name, inputValue);
2172
+ if (disabled || (!disabled && !isUndefined(inputValue))) {
2173
+ set(_formValues, name, inputValue);
2174
+ }
2160
2175
  updateTouchAndDirty(name, inputValue, false, false, true);
2161
2176
  }
2162
2177
  };
@@ -2385,7 +2400,7 @@ function createFormControl(props = {}) {
2385
2400
  }
2386
2401
  _fields = {};
2387
2402
  }
2388
- _formValues = props.shouldUnregister
2403
+ _formValues = _options.shouldUnregister
2389
2404
  ? keepStateOptions.keepDefaultValues
2390
2405
  ? cloneObject(_defaultValues)
2391
2406
  : {}
@@ -2409,7 +2424,7 @@ function createFormControl(props = {}) {
2409
2424
  !_proxyFormState.isValid ||
2410
2425
  !!keepStateOptions.keepIsValid ||
2411
2426
  !!keepStateOptions.keepDirtyValues;
2412
- _state.watch = !!props.shouldUnregister;
2427
+ _state.watch = !!_options.shouldUnregister;
2413
2428
  _subjects.state.next({
2414
2429
  submitCount: keepStateOptions.keepSubmitCount
2415
2430
  ? _formState.submitCount
@@ -2659,8 +2674,10 @@ function useForm(props = {}) {
2659
2674
  values: control._getWatch(),
2660
2675
  });
2661
2676
  }, [props.shouldUnregister, control]);
2662
- _formControl.current.formState = getProxyFormState(formState, control);
2663
- return _formControl.current;
2677
+ return React.useMemo(() => ({
2678
+ ..._formControl.current,
2679
+ formState: getProxyFormState(formState, control),
2680
+ }), [formState, control]);
2664
2681
  }
2665
2682
 
2666
2683
  export { Controller, Form, FormProvider, appendErrors, get, set, useController, useFieldArray, useForm, useFormContext, useFormState, useWatch };