react-hook-form 7.36.1 → 7.37.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.
@@ -127,14 +127,16 @@ const FormProvider = (props) => {
127
127
  return (React.createElement(HookFormContext.Provider, { value: data }, children));
128
128
  };
129
129
 
130
- var getProxyFormState = (formState, _proxyFormState, localProxyFormState, isRoot = true) => {
131
- const result = {};
130
+ var getProxyFormState = (formState, control, localProxyFormState, isRoot = true) => {
131
+ const result = {
132
+ defaultValues: control._defaultValues,
133
+ };
132
134
  for (const key in formState) {
133
135
  Object.defineProperty(result, key, {
134
136
  get: () => {
135
137
  const _key = key;
136
- if (_proxyFormState[_key] !== VALIDATION_MODE.all) {
137
- _proxyFormState[_key] = !isRoot || VALIDATION_MODE.all;
138
+ if (control._proxyFormState[_key] !== VALIDATION_MODE.all) {
139
+ control._proxyFormState[_key] = !isRoot || VALIDATION_MODE.all;
138
140
  }
139
141
  localProxyFormState && (localProxyFormState[_key] = true);
140
142
  return formState[_key];
@@ -169,16 +171,13 @@ function useSubscribe(props) {
169
171
  const _props = React.useRef(props);
170
172
  _props.current = props;
171
173
  React.useEffect(() => {
172
- const tearDown = (subscription) => {
173
- if (subscription) {
174
- subscription.unsubscribe();
175
- }
176
- };
177
174
  const subscription = !props.disabled &&
178
175
  _props.current.subject.subscribe({
179
176
  next: _props.current.callback,
180
177
  });
181
- return () => tearDown(subscription);
178
+ return () => {
179
+ subscription && subscription.unsubscribe();
180
+ };
182
181
  }, [props.disabled]);
183
182
  }
184
183
 
@@ -216,6 +215,7 @@ function useFormState(props) {
216
215
  const methods = useFormContext();
217
216
  const { control = methods.control, disabled, name, exact } = props || {};
218
217
  const [formState, updateFormState] = React.useState(control._formState);
218
+ const _mounted = React.useRef(true);
219
219
  const _localProxyFormState = React.useRef({
220
220
  isDirty: false,
221
221
  dirtyFields: false,
@@ -225,18 +225,16 @@ function useFormState(props) {
225
225
  errors: false,
226
226
  });
227
227
  const _name = React.useRef(name);
228
- const _mounted = React.useRef(true);
229
228
  _name.current = name;
230
- const callback = React.useCallback((value) => _mounted.current &&
231
- shouldSubscribeByName(_name.current, value.name, exact) &&
232
- shouldRenderFormState(value, _localProxyFormState.current) &&
233
- updateFormState({
234
- ...control._formState,
235
- ...value,
236
- }), [control, exact]);
237
229
  useSubscribe({
238
230
  disabled,
239
- callback,
231
+ callback: React.useCallback((value) => _mounted.current &&
232
+ shouldSubscribeByName(_name.current, value.name, exact) &&
233
+ shouldRenderFormState(value, _localProxyFormState.current) &&
234
+ updateFormState({
235
+ ...control._formState,
236
+ ...value,
237
+ }), [control, exact]),
240
238
  subject: control._subjects.state,
241
239
  });
242
240
  React.useEffect(() => {
@@ -245,7 +243,7 @@ function useFormState(props) {
245
243
  _mounted.current = false;
246
244
  };
247
245
  }, []);
248
- return getProxyFormState(formState, control._proxyFormState, _localProxyFormState.current, false);
246
+ return getProxyFormState(formState, control, _localProxyFormState.current, false);
249
247
  }
250
248
 
251
249
  var isString = (value) => typeof value === 'string';
@@ -296,30 +294,27 @@ function useWatch(props) {
296
294
  const { control = methods.control, name, defaultValue, disabled, exact, } = props || {};
297
295
  const _name = React.useRef(name);
298
296
  _name.current = name;
299
- const callback = React.useCallback((formState) => {
300
- if (shouldSubscribeByName(_name.current, formState.name, exact)) {
301
- const fieldValues = generateWatchOutput(_name.current, control._names, formState.values || control._formValues);
302
- updateValue(isUndefined(_name.current) ||
303
- (isObject(fieldValues) && !objectHasFunction(fieldValues))
304
- ? { ...fieldValues }
305
- : Array.isArray(fieldValues)
306
- ? [...fieldValues]
307
- : isUndefined(fieldValues)
308
- ? defaultValue
309
- : fieldValues);
310
- }
311
- }, [control, exact, defaultValue]);
312
297
  useSubscribe({
313
298
  disabled,
314
299
  subject: control._subjects.watch,
315
- callback,
300
+ callback: React.useCallback((formState) => {
301
+ if (shouldSubscribeByName(_name.current, formState.name, exact)) {
302
+ const fieldValues = generateWatchOutput(_name.current, control._names, formState.values || control._formValues);
303
+ updateValue(isUndefined(_name.current) ||
304
+ (isObject(fieldValues) && !objectHasFunction(fieldValues))
305
+ ? { ...fieldValues }
306
+ : Array.isArray(fieldValues)
307
+ ? [...fieldValues]
308
+ : isUndefined(fieldValues)
309
+ ? defaultValue
310
+ : fieldValues);
311
+ }
312
+ }, [control, exact, defaultValue]),
316
313
  });
317
314
  const [value, updateValue] = React.useState(isUndefined(defaultValue)
318
315
  ? control._getWatch(name)
319
316
  : defaultValue);
320
- React.useEffect(() => {
321
- control._removeUnmounted();
322
- });
317
+ React.useEffect(() => control._removeUnmounted());
323
318
  return value;
324
319
  }
325
320
 
@@ -386,27 +381,23 @@ function useController(props) {
386
381
  field: {
387
382
  name,
388
383
  value,
389
- onChange: React.useCallback((event) => {
390
- _registerProps.current.onChange({
391
- target: {
392
- value: getEventValue(event),
393
- name: name,
394
- },
395
- type: EVENTS.CHANGE,
396
- });
397
- }, [name]),
398
- onBlur: React.useCallback(() => {
399
- _registerProps.current.onBlur({
400
- target: {
401
- value: get(control._formValues, name),
402
- name: name,
403
- },
404
- type: EVENTS.BLUR,
405
- });
406
- }, [name, control]),
407
- ref: React.useCallback((elm) => {
384
+ onChange: React.useCallback((event) => _registerProps.current.onChange({
385
+ target: {
386
+ value: getEventValue(event),
387
+ name: name,
388
+ },
389
+ type: EVENTS.CHANGE,
390
+ }), [name]),
391
+ onBlur: React.useCallback(() => _registerProps.current.onBlur({
392
+ target: {
393
+ value: get(control._formValues, name),
394
+ name: name,
395
+ },
396
+ type: EVENTS.BLUR,
397
+ }), [name, control]),
398
+ ref: (elm) => {
408
399
  const field = get(control._fields, name);
409
- if (elm && field && elm.focus) {
400
+ if (field && elm) {
410
401
  field._f.ref = {
411
402
  focus: () => elm.focus(),
412
403
  select: () => elm.select(),
@@ -414,7 +405,7 @@ function useController(props) {
414
405
  reportValidity: () => elm.reportValidity(),
415
406
  };
416
407
  }
417
- }, [name, control._fields]),
408
+ },
418
409
  },
419
410
  formState,
420
411
  fieldState: Object.defineProperties({}, {
@@ -525,10 +516,11 @@ const focusFieldBy = (fields, callback, fieldsNames) => {
525
516
  if (field) {
526
517
  const { _f, ...currentField } = field;
527
518
  if (_f && callback(_f.name)) {
528
- if (_f.ref.focus && isUndefined(_f.ref.focus())) {
519
+ if (_f.ref.focus) {
520
+ _f.ref.focus();
529
521
  break;
530
522
  }
531
- else if (_f.refs) {
523
+ else if (_f.refs && _f.refs[0].focus) {
532
524
  _f.refs[0].focus();
533
525
  break;
534
526
  }
@@ -801,6 +793,11 @@ function append(data, value) {
801
793
  return [...data, ...convertToArrayPayload(value)];
802
794
  }
803
795
 
796
+ var isPlainObject = (tempObject) => {
797
+ const prototypeCopy = tempObject.constructor && tempObject.constructor.prototype;
798
+ return (isObject(prototypeCopy) && prototypeCopy.hasOwnProperty('isPrototypeOf'));
799
+ };
800
+
804
801
  var isWeb = typeof window !== 'undefined' &&
805
802
  typeof window.HTMLElement !== 'undefined' &&
806
803
  typeof document !== 'undefined';
@@ -817,12 +814,13 @@ function cloneObject(data) {
817
814
  else if (!(isWeb && (data instanceof Blob || data instanceof FileList)) &&
818
815
  (isArray || isObject(data))) {
819
816
  copy = isArray ? [] : {};
820
- for (const key in data) {
821
- if (isFunction(data[key])) {
822
- copy = data;
823
- break;
817
+ if (!Array.isArray(data) && !isPlainObject(data)) {
818
+ copy = data;
819
+ }
820
+ else {
821
+ for (const key in data) {
822
+ copy[key] = cloneObject(data[key]);
824
823
  }
825
- copy[key] = cloneObject(data[key]);
826
824
  }
827
825
  }
828
826
  else {
@@ -1083,7 +1081,9 @@ function useFieldArray(props) {
1083
1081
  React.useEffect(() => {
1084
1082
  control._stateFlags.action = false;
1085
1083
  isWatched(name, control._names) && control._subjects.state.next({});
1086
- if (_actioned.current) {
1084
+ if (_actioned.current &&
1085
+ (!getValidationModes(control._options.mode).isOnSubmit ||
1086
+ control._formState.isSubmitted)) {
1087
1087
  if (control._options.resolver) {
1088
1088
  control._executeSchema([name]).then((result) => {
1089
1089
  const error = get(result.errors, name);
@@ -1100,11 +1100,7 @@ function useFieldArray(props) {
1100
1100
  }
1101
1101
  else {
1102
1102
  const field = get(control._fields, name);
1103
- const validationModeBeforeSubmit = getValidationModes(control._options.mode);
1104
- if ((!validationModeBeforeSubmit.isOnSubmit ||
1105
- control._formState.isSubmitted) &&
1106
- field &&
1107
- field._f) {
1103
+ if (field && field._f) {
1108
1104
  validateField(field, get(control._formValues, name), control._options.criteriaMode === VALIDATION_MODE.all, control._options.shouldUseNativeValidation, true).then((error) => !isEmptyObject(error) &&
1109
1105
  control._subjects.state.next({
1110
1106
  errors: updateFieldArrayRootError(control._formState.errors, error, name),
@@ -1383,15 +1379,15 @@ function createFormControl(props = {}) {
1383
1379
  ...props,
1384
1380
  };
1385
1381
  let _formState = {
1382
+ submitCount: 0,
1386
1383
  isDirty: false,
1387
1384
  isValidating: false,
1388
- dirtyFields: {},
1389
1385
  isSubmitted: false,
1390
- submitCount: 0,
1391
- touchedFields: {},
1392
1386
  isSubmitting: false,
1393
1387
  isSubmitSuccessful: false,
1394
1388
  isValid: false,
1389
+ touchedFields: {},
1390
+ dirtyFields: {},
1395
1391
  errors: {},
1396
1392
  };
1397
1393
  let _fields = {};
@@ -1657,7 +1653,7 @@ function createFormControl(props = {}) {
1657
1653
  ? ''
1658
1654
  : value;
1659
1655
  if (isMultipleSelect(fieldReference.ref)) {
1660
- [...fieldReference.ref.options].forEach((selectRef) => (selectRef.selected = fieldValue.includes(selectRef.value)));
1656
+ [...fieldReference.ref.options].forEach((optionRef) => (optionRef.selected = fieldValue.includes(optionRef.value)));
1661
1657
  }
1662
1658
  else if (fieldReference.refs) {
1663
1659
  if (isCheckBoxInput(fieldReference.ref)) {
@@ -2130,9 +2126,7 @@ function createFormControl(props = {}) {
2130
2126
  touchedFields: keepStateOptions.keepTouched
2131
2127
  ? _formState.touchedFields
2132
2128
  : {},
2133
- errors: keepStateOptions.keepErrors
2134
- ? _formState.errors
2135
- : {},
2129
+ errors: keepStateOptions.keepErrors ? _formState.errors : {},
2136
2130
  isSubmitting: false,
2137
2131
  isSubmitSuccessful: false,
2138
2132
  });
@@ -2147,8 +2141,10 @@ function createFormControl(props = {}) {
2147
2141
  const fieldRef = fieldReference.refs
2148
2142
  ? fieldReference.refs[0]
2149
2143
  : fieldReference.ref;
2150
- fieldRef.focus();
2151
- options.shouldSelect && fieldRef.select();
2144
+ if (fieldRef.focus) {
2145
+ fieldRef.focus();
2146
+ options.shouldSelect && fieldRef.select();
2147
+ }
2152
2148
  }
2153
2149
  };
2154
2150
  return {
@@ -2252,37 +2248,35 @@ function useForm(props = {}) {
2252
2248
  const [formState, updateFormState] = React.useState({
2253
2249
  isDirty: false,
2254
2250
  isValidating: false,
2255
- dirtyFields: {},
2256
2251
  isSubmitted: false,
2257
- submitCount: 0,
2258
- touchedFields: {},
2259
2252
  isSubmitting: false,
2260
2253
  isSubmitSuccessful: false,
2261
2254
  isValid: false,
2255
+ submitCount: 0,
2256
+ dirtyFields: {},
2257
+ touchedFields: {},
2262
2258
  errors: {},
2259
+ defaultValues: props.defaultValues,
2263
2260
  });
2264
- if (_formControl.current) {
2265
- _formControl.current.control._options = props;
2266
- }
2267
- else {
2261
+ if (!_formControl.current) {
2268
2262
  _formControl.current = {
2269
2263
  ...createFormControl(props),
2270
2264
  formState,
2271
2265
  };
2272
2266
  }
2273
2267
  const control = _formControl.current.control;
2274
- const callback = React.useCallback((value) => {
2275
- if (shouldRenderFormState(value, control._proxyFormState, true)) {
2276
- control._formState = {
2277
- ...control._formState,
2278
- ...value,
2279
- };
2280
- updateFormState({ ...control._formState });
2281
- }
2282
- }, [control]);
2268
+ control._options = props;
2283
2269
  useSubscribe({
2284
2270
  subject: control._subjects.state,
2285
- callback,
2271
+ callback: React.useCallback((value) => {
2272
+ if (shouldRenderFormState(value, control._proxyFormState, true)) {
2273
+ control._formState = {
2274
+ ...control._formState,
2275
+ ...value,
2276
+ };
2277
+ updateFormState({ ...control._formState });
2278
+ }
2279
+ }, [control]),
2286
2280
  });
2287
2281
  React.useEffect(() => {
2288
2282
  if (!control._stateFlags.mount) {
@@ -2295,7 +2289,7 @@ function useForm(props = {}) {
2295
2289
  }
2296
2290
  control._removeUnmounted();
2297
2291
  });
2298
- _formControl.current.formState = getProxyFormState(formState, control._proxyFormState);
2292
+ _formControl.current.formState = getProxyFormState(formState, control);
2299
2293
  return _formControl.current;
2300
2294
  }
2301
2295