react-hook-form 7.78.0 → 7.79.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.
@@ -249,7 +249,7 @@ var generateWatchOutput = (names, _names, formValues, isGlobal, defaultValue) =>
249
249
  var isPrimitive = (value) => isNullOrUndefined(value) || !isObjectType(value);
250
250
 
251
251
  const isEmptyObjectWithCustomPrototype = (object, keys) => keys.length === 0 && !Array.isArray(object) && !isPlainObject(object);
252
- function deepEqual(object1, object2, visited = new WeakSet()) {
252
+ function deepEqual(object1, object2, visited = new WeakMap()) {
253
253
  if (object1 === object2) {
254
254
  return true;
255
255
  }
@@ -268,11 +268,16 @@ function deepEqual(object1, object2, visited = new WeakSet()) {
268
268
  isEmptyObjectWithCustomPrototype(object2, keys2)) {
269
269
  return Object.is(object1, object2);
270
270
  }
271
- if (visited.has(object1) || visited.has(object2)) {
271
+ const visitedPairs = visited.get(object1);
272
+ if (visitedPairs && visitedPairs.has(object2)) {
272
273
  return true;
273
274
  }
274
- visited.add(object1);
275
- visited.add(object2);
275
+ if (visitedPairs) {
276
+ visitedPairs.add(object2);
277
+ }
278
+ else {
279
+ visited.set(object1, new WeakSet([object2]));
280
+ }
276
281
  for (const key of keys1) {
277
282
  const val1 = object1[key];
278
283
  if (!(key in object2)) {
@@ -419,6 +424,7 @@ function useController(props) {
419
424
  exact,
420
425
  });
421
426
  const _props = React.useRef(props);
427
+ const _proxyRef = React.useRef(null);
422
428
  const _registerProps = React.useRef(control.register(name, {
423
429
  ...props.rules,
424
430
  value,
@@ -455,7 +461,7 @@ function useController(props) {
455
461
  value,
456
462
  });
457
463
  }
458
- _registerProps.current.onChange({
464
+ return _registerProps.current.onChange({
459
465
  target: {
460
466
  value: getEventValue(event),
461
467
  name: name,
@@ -471,15 +477,18 @@ function useController(props) {
471
477
  type: EVENTS.BLUR,
472
478
  }), [name, control._formValues]);
473
479
  const ref = React.useCallback((elm) => {
474
- const field = get(control._fields, name);
475
- if (field && field._f && elm) {
476
- field._f.ref = {
480
+ if (elm) {
481
+ _proxyRef.current = {
477
482
  focus: () => isFunction(elm.focus) && elm.focus(),
478
483
  select: () => isFunction(elm.select) && elm.select(),
479
484
  setCustomValidity: (message) => isFunction(elm.setCustomValidity) && elm.setCustomValidity(message),
480
485
  reportValidity: () => isFunction(elm.reportValidity) && elm.reportValidity(),
481
486
  };
482
487
  }
488
+ const field = get(control._fields, name);
489
+ if (field && field._f && elm) {
490
+ field._f.ref = _proxyRef.current;
491
+ }
483
492
  }, [control._fields, name]);
484
493
  const field = React.useMemo(() => ({
485
494
  name,
@@ -516,6 +525,12 @@ function useController(props) {
516
525
  }
517
526
  }
518
527
  !isArrayField && control.register(name);
528
+ if (_proxyRef.current) {
529
+ const field = get(control._fields, name);
530
+ if (field && field._f) {
531
+ field._f.ref = _proxyRef.current;
532
+ }
533
+ }
519
534
  return () => {
520
535
  (isArrayField
521
536
  ? _shouldUnregisterField && !control._state.action
@@ -1274,7 +1289,13 @@ var validateField = async (field, disabledFieldNames, formValues, validateAllFie
1274
1289
  const inputRef = refs ? refs[0] : ref;
1275
1290
  const setCustomValidity = (message) => {
1276
1291
  if (shouldUseNativeValidation && inputRef.reportValidity) {
1277
- inputRef.setCustomValidity(isBoolean(message) ? '' : message || '');
1292
+ const validityMessage = isBoolean(message) ? '' : message || '';
1293
+ if (refs) {
1294
+ refs.forEach((ref) => ref.setCustomValidity(validityMessage));
1295
+ }
1296
+ else {
1297
+ inputRef.setCustomValidity(validityMessage);
1298
+ }
1278
1299
  inputRef.reportValidity();
1279
1300
  }
1280
1301
  };
@@ -1606,6 +1627,7 @@ function createFormControl(props = {}) {
1606
1627
  };
1607
1628
  const updateErrors = (name, error) => {
1608
1629
  set(_formState.errors, name, error);
1630
+ _formState.errors = { ..._formState.errors };
1609
1631
  _subjects.state.next({
1610
1632
  errors: _formState.errors,
1611
1633
  });
@@ -1663,6 +1685,15 @@ function createFormControl(props = {}) {
1663
1685
  _subjects.state.next({ ..._formState });
1664
1686
  }
1665
1687
  }
1688
+ // When a watched field is re-registered after being unregistered and
1689
+ // its value is restored, trigger a deferred watch broadcast so that
1690
+ // components using watch() re-render with the new value.
1691
+ if (props.shouldUnregister &&
1692
+ wasUnsetInFormValues &&
1693
+ !isUndefined(get(_formValues, name)) &&
1694
+ isWatched(name, _names)) {
1695
+ _state.watch = true;
1696
+ }
1666
1697
  }
1667
1698
  }
1668
1699
  };
@@ -1727,6 +1758,7 @@ function createFormControl(props = {}) {
1727
1758
  error
1728
1759
  ? set(_formState.errors, name, error)
1729
1760
  : unset(_formState.errors, name);
1761
+ _formState.errors = { ..._formState.errors };
1730
1762
  }
1731
1763
  if ((error ? !deepEqual(previousFieldError, error) : previousFieldError) ||
1732
1764
  !isEmptyObject(fieldState) ||
@@ -1762,6 +1794,7 @@ function createFormControl(props = {}) {
1762
1794
  : set(_formState.errors, name, error)
1763
1795
  : unset(_formState.errors, name);
1764
1796
  }
1797
+ _formState.errors = { ..._formState.errors };
1765
1798
  }
1766
1799
  else {
1767
1800
  _formState.errors = errors;
@@ -2875,34 +2908,45 @@ var updateAt = (fieldValues, index, value) => {
2875
2908
  */
2876
2909
  function useFieldArray(props) {
2877
2910
  const formControl = useFormControlContext();
2878
- const { control = formControl, name, keyName = 'id', shouldUnregister, rules, } = props;
2879
- const [fields, setFields] = React.useState(control._getFieldArray(name));
2880
- const ids = React.useRef(control._getFieldArray(name).map(generateId));
2911
+ const { control = formControl, name, keyName = 'id', disabled, shouldUnregister, rules, } = props;
2912
+ const [fields, setFields] = React.useState(disabled ? [] : control._getFieldArray(name));
2913
+ const ids = React.useRef(disabled ? [] : control._getFieldArray(name).map(generateId));
2881
2914
  const _actioned = React.useRef(false);
2882
- control._names.array.add(name);
2883
- React.useMemo(() => rules &&
2915
+ if (!disabled) {
2916
+ control._names.array.add(name);
2917
+ }
2918
+ React.useMemo(() => !disabled &&
2919
+ rules &&
2884
2920
  fields.length >= 0 &&
2885
- control.register(name, rules), [control, name, fields.length, rules]);
2886
- useIsomorphicLayoutEffect(() => control._subjects.array.subscribe({
2887
- next: ({ values, name: fieldArrayName, }) => {
2888
- if (fieldArrayName === name || !fieldArrayName) {
2889
- const fieldValues = get(values, name);
2890
- if (Array.isArray(fieldValues)) {
2891
- setFields(fieldValues);
2892
- ids.current = fieldValues.map(generateId);
2893
- }
2894
- else if (!fieldArrayName) {
2895
- setFields([]);
2896
- ids.current = [];
2921
+ control.register(name, rules), [control, name, fields.length, rules, disabled]);
2922
+ useIsomorphicLayoutEffect(() => {
2923
+ if (disabled) {
2924
+ return;
2925
+ }
2926
+ return control._subjects.array.subscribe({
2927
+ next: ({ values, name: fieldArrayName, }) => {
2928
+ if (fieldArrayName === name || !fieldArrayName) {
2929
+ const fieldValues = get(values, name);
2930
+ if (Array.isArray(fieldValues)) {
2931
+ setFields(fieldValues);
2932
+ ids.current = fieldValues.map(generateId);
2933
+ }
2934
+ else if (!fieldArrayName) {
2935
+ setFields([]);
2936
+ ids.current = [];
2937
+ }
2897
2938
  }
2898
- }
2899
- },
2900
- }).unsubscribe, [control, name]);
2939
+ },
2940
+ }).unsubscribe;
2941
+ }, [control, name, disabled]);
2901
2942
  const updateValues = React.useCallback((updatedFieldArrayValues) => {
2902
2943
  _actioned.current = true;
2903
2944
  control._setFieldArray(name, updatedFieldArrayValues);
2904
2945
  }, [control, name]);
2905
2946
  const append = (value, options) => {
2947
+ if (disabled) {
2948
+ return;
2949
+ }
2906
2950
  const appendValue = convertToArrayPayload(cloneObject(value));
2907
2951
  const updatedFieldArrayValues = appendAt(control._getFieldArray(name), appendValue);
2908
2952
  control._names.focus = getFocusFieldName(name, updatedFieldArrayValues.length - 1, options);
@@ -2914,6 +2958,9 @@ function useFieldArray(props) {
2914
2958
  });
2915
2959
  };
2916
2960
  const prepend = (value, options) => {
2961
+ if (disabled) {
2962
+ return;
2963
+ }
2917
2964
  const prependValue = convertToArrayPayload(cloneObject(value));
2918
2965
  const updatedFieldArrayValues = prependAt(control._getFieldArray(name), prependValue);
2919
2966
  control._names.focus = getFocusFieldName(name, 0, options);
@@ -2925,6 +2972,9 @@ function useFieldArray(props) {
2925
2972
  });
2926
2973
  };
2927
2974
  const remove = (index) => {
2975
+ if (disabled) {
2976
+ return;
2977
+ }
2928
2978
  const updatedFieldArrayValues = removeArrayAt(control._getFieldArray(name), index);
2929
2979
  ids.current = removeArrayAt(ids.current, index);
2930
2980
  updateValues(updatedFieldArrayValues);
@@ -2936,6 +2986,9 @@ function useFieldArray(props) {
2936
2986
  });
2937
2987
  };
2938
2988
  const insert$1 = (index, value, options) => {
2989
+ if (disabled) {
2990
+ return;
2991
+ }
2939
2992
  const insertValue = convertToArrayPayload(cloneObject(value));
2940
2993
  const updatedFieldArrayValues = insert(control._getFieldArray(name), index, insertValue);
2941
2994
  control._names.focus = getFocusFieldName(name, index, options);
@@ -2948,6 +3001,9 @@ function useFieldArray(props) {
2948
3001
  });
2949
3002
  };
2950
3003
  const swap = (indexA, indexB) => {
3004
+ if (disabled) {
3005
+ return;
3006
+ }
2951
3007
  const updatedFieldArrayValues = control._getFieldArray(name);
2952
3008
  swapArrayAt(updatedFieldArrayValues, indexA, indexB);
2953
3009
  swapArrayAt(ids.current, indexA, indexB);
@@ -2959,6 +3015,9 @@ function useFieldArray(props) {
2959
3015
  }, false);
2960
3016
  };
2961
3017
  const move = (from, to) => {
3018
+ if (disabled) {
3019
+ return;
3020
+ }
2962
3021
  const updatedFieldArrayValues = control._getFieldArray(name);
2963
3022
  moveArrayAt(updatedFieldArrayValues, from, to);
2964
3023
  moveArrayAt(ids.current, from, to);
@@ -2970,6 +3029,9 @@ function useFieldArray(props) {
2970
3029
  }, false);
2971
3030
  };
2972
3031
  const update = (index, value) => {
3032
+ if (disabled) {
3033
+ return;
3034
+ }
2973
3035
  const updateValue = cloneObject(value);
2974
3036
  const updatedFieldArrayValues = updateAt(control._getFieldArray(name), index, updateValue);
2975
3037
  ids.current = [...updatedFieldArrayValues].map((item, i) => !item || i === index ? generateId() : ids.current[i]);
@@ -2981,6 +3043,9 @@ function useFieldArray(props) {
2981
3043
  }, true, false);
2982
3044
  };
2983
3045
  const replace = (value) => {
3046
+ if (disabled) {
3047
+ return;
3048
+ }
2984
3049
  const updatedFieldArrayValues = convertToArrayPayload(cloneObject(value));
2985
3050
  ids.current = updatedFieldArrayValues.map(generateId);
2986
3051
  updateValues([...updatedFieldArrayValues]);
@@ -2988,6 +3053,9 @@ function useFieldArray(props) {
2988
3053
  control._setFieldArray(name, [...updatedFieldArrayValues], (data) => data, {}, true, false);
2989
3054
  };
2990
3055
  React.useEffect(() => {
3056
+ if (disabled) {
3057
+ return;
3058
+ }
2991
3059
  control._state.action = false;
2992
3060
  isWatched(name, control._names) &&
2993
3061
  control._subjects.state.next({
@@ -3048,10 +3116,15 @@ function useFieldArray(props) {
3048
3116
  control._names.focus = '';
3049
3117
  control._setValid();
3050
3118
  _actioned.current = false;
3051
- }, [fields, name, control]);
3119
+ }, [fields, name, control, disabled]);
3052
3120
  React.useEffect(() => {
3053
- !get(control._formValues, name) && control._setFieldArray(name);
3121
+ if (!disabled) {
3122
+ !get(control._formValues, name) && control._setFieldArray(name);
3123
+ }
3054
3124
  return () => {
3125
+ if (disabled) {
3126
+ return;
3127
+ }
3055
3128
  const shouldKeepFieldArrayValues = !(control._options.shouldUnregister || shouldUnregister);
3056
3129
  const updateMounted = (name, value) => {
3057
3130
  const field = get(control._fields, name);
@@ -3069,16 +3142,26 @@ function useFieldArray(props) {
3069
3142
  ? updateMounted(name, false)
3070
3143
  : control.unregister(name);
3071
3144
  };
3072
- }, [name, control, keyName, shouldUnregister]);
3145
+ }, [name, control, keyName, shouldUnregister, disabled]);
3073
3146
  return {
3074
- swap: React.useCallback(swap, [updateValues, name, control]),
3075
- move: React.useCallback(move, [updateValues, name, control]),
3076
- prepend: React.useCallback(prepend, [updateValues, name, control]),
3077
- append: React.useCallback(append, [updateValues, name, control]),
3078
- remove: React.useCallback(remove, [updateValues, name, control]),
3079
- insert: React.useCallback(insert$1, [updateValues, name, control]),
3080
- update: React.useCallback(update, [updateValues, name, control]),
3081
- replace: React.useCallback(replace, [updateValues, name, control]),
3147
+ swap: React.useCallback(swap, [updateValues, name, control, disabled]),
3148
+ move: React.useCallback(move, [updateValues, name, control, disabled]),
3149
+ prepend: React.useCallback(prepend, [
3150
+ updateValues,
3151
+ name,
3152
+ control,
3153
+ disabled,
3154
+ ]),
3155
+ append: React.useCallback(append, [updateValues, name, control, disabled]),
3156
+ remove: React.useCallback(remove, [updateValues, name, control, disabled]),
3157
+ insert: React.useCallback(insert$1, [updateValues, name, control, disabled]),
3158
+ update: React.useCallback(update, [updateValues, name, control, disabled]),
3159
+ replace: React.useCallback(replace, [
3160
+ updateValues,
3161
+ name,
3162
+ control,
3163
+ disabled,
3164
+ ]),
3082
3165
  fields: React.useMemo(() => fields.map((field, index) => ({
3083
3166
  ...field,
3084
3167
  [keyName]: ids.current[index] || generateId(),
@@ -3118,6 +3201,7 @@ function useFieldArray(props) {
3118
3201
  function useForm(props = {}) {
3119
3202
  const _formControl = React.useRef(undefined);
3120
3203
  const _values = React.useRef(undefined);
3204
+ const _formControlProp = React.useRef(props.formControl);
3121
3205
  const [formState, updateFormState] = React.useState(() => ({
3122
3206
  ...cloneObject(DEFAULT_FORM_STATE),
3123
3207
  isLoading: isFunction(props.defaultValues),
@@ -3127,7 +3211,9 @@ function useForm(props = {}) {
3127
3211
  ? undefined
3128
3212
  : props.defaultValues,
3129
3213
  }));
3130
- if (!_formControl.current) {
3214
+ if (!_formControl.current ||
3215
+ (props.formControl && _formControlProp.current !== props.formControl)) {
3216
+ _formControlProp.current = props.formControl;
3131
3217
  if (props.formControl) {
3132
3218
  _formControl.current = {
3133
3219
  ...props.formControl,