react-hook-form 7.19.4 → 7.20.2

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.
package/dist/index.esm.js CHANGED
@@ -103,43 +103,35 @@ var shouldRenderFormState = (formStateData, _proxyFormState, isRoot) => {
103
103
 
104
104
  var convertToArrayPayload = (value) => (Array.isArray(value) ? value : [value]);
105
105
 
106
- var shouldSubscribeByName = (name, signalName) => !name ||
107
- !signalName ||
108
- name === signalName ||
109
- convertToArrayPayload(name).some((currentName) => currentName &&
110
- (currentName.startsWith(signalName) ||
111
- signalName.startsWith(currentName)));
112
-
113
- const tearDown = (_subscription) => {
114
- if (_subscription.current) {
115
- _subscription.current.unsubscribe();
116
- _subscription.current = undefined;
117
- }
118
- };
119
- const updateSubscriptionProps = ({ _subscription, props }) => {
120
- if (props.disabled) {
121
- tearDown(_subscription);
122
- }
123
- else if (!_subscription.current) {
124
- _subscription.current = props.subject.subscribe({
125
- next: props.callback,
126
- });
127
- }
128
- };
106
+ var shouldSubscribeByName = (name, signalName, exact) => exact && signalName
107
+ ? name === signalName
108
+ : !name ||
109
+ !signalName ||
110
+ name === signalName ||
111
+ convertToArrayPayload(name).some((currentName) => currentName &&
112
+ (currentName.startsWith(signalName) ||
113
+ signalName.startsWith(currentName)));
114
+
129
115
  function useSubscribe(props) {
130
- const _subscription = React.useRef();
131
- updateSubscriptionProps({
132
- _subscription,
133
- props,
134
- });
116
+ const _props = React.useRef(props);
117
+ _props.current = props;
135
118
  React.useEffect(() => {
136
- return () => tearDown(_subscription);
137
- }, []);
119
+ const tearDown = (subscription) => {
120
+ if (subscription) {
121
+ subscription.unsubscribe();
122
+ }
123
+ };
124
+ const subscription = !props.disabled &&
125
+ _props.current.subject.subscribe({
126
+ next: _props.current.callback,
127
+ });
128
+ return () => tearDown(subscription);
129
+ }, [props.disabled]);
138
130
  }
139
131
 
140
132
  function useFormState(props) {
141
133
  const methods = useFormContext();
142
- const { control = methods.control, disabled, name } = props || {};
134
+ const { control = methods.control, disabled, name, exact } = props || {};
143
135
  const [formState, updateFormState] = React.useState(control._formState);
144
136
  const _localProxyFormState = React.useRef({
145
137
  isDirty: false,
@@ -153,9 +145,9 @@ function useFormState(props) {
153
145
  _name.current = name;
154
146
  useSubscribe({
155
147
  disabled,
156
- callback: (formState) => shouldSubscribeByName(_name.current, formState.name) &&
157
- shouldRenderFormState(formState, _localProxyFormState.current) &&
158
- updateFormState(Object.assign(Object.assign({}, control._formState), formState)),
148
+ callback: (value) => shouldSubscribeByName(_name.current, value.name, exact) &&
149
+ shouldRenderFormState(value, _localProxyFormState.current) &&
150
+ updateFormState(Object.assign(Object.assign({}, control._formState), value)),
159
151
  subject: control._subjects.state,
160
152
  });
161
153
  return getProxyFormState(formState, control._proxyFormState, _localProxyFormState.current, false);
@@ -163,7 +155,7 @@ function useFormState(props) {
163
155
 
164
156
  var isString = (value) => typeof value === 'string';
165
157
 
166
- function generateWatchOutput(names, _names, formValues, isGlobal) {
158
+ var generateWatchOutput = (names, _names, formValues, isGlobal) => {
167
159
  const isArray = Array.isArray(names);
168
160
  if (isString(names)) {
169
161
  isGlobal && _names.watch.add(names);
@@ -175,20 +167,32 @@ function generateWatchOutput(names, _names, formValues, isGlobal) {
175
167
  }
176
168
  isGlobal && (_names.watchAll = true);
177
169
  return formValues;
178
- }
170
+ };
171
+
172
+ var isFunction = (value) => typeof value === 'function';
173
+
174
+ var objectHasFunction = (data) => {
175
+ for (const key in data) {
176
+ if (isFunction(data[key])) {
177
+ return true;
178
+ }
179
+ }
180
+ return false;
181
+ };
179
182
 
180
183
  function useWatch(props) {
181
184
  const methods = useFormContext();
182
- const { control = methods.control, name, defaultValue, disabled, } = props || {};
185
+ const { control = methods.control, name, defaultValue, disabled, exact, } = props || {};
183
186
  const _name = React.useRef(name);
184
187
  _name.current = name;
185
188
  useSubscribe({
186
189
  disabled,
187
190
  subject: control._subjects.watch,
188
191
  callback: (formState) => {
189
- if (shouldSubscribeByName(_name.current, formState.name)) {
192
+ if (shouldSubscribeByName(_name.current, formState.name, exact)) {
190
193
  const fieldValues = generateWatchOutput(_name.current, control._names, formState.values || control._formValues);
191
- updateValue(isUndefined(_name.current)
194
+ updateValue(isUndefined(_name.current) ||
195
+ (isObject(fieldValues) && !objectHasFunction(fieldValues))
192
196
  ? Object.assign({}, fieldValues) : Array.isArray(fieldValues)
193
197
  ? [...fieldValues]
194
198
  : fieldValues);
@@ -207,10 +211,12 @@ function useWatch(props) {
207
211
  function useController(props) {
208
212
  const methods = useFormContext();
209
213
  const { name, control = methods.control, shouldUnregister } = props;
214
+ const isArrayField = isNameInFieldArray(control._names.array, name);
210
215
  const value = useWatch({
211
216
  control,
212
217
  name,
213
218
  defaultValue: get(control._formValues, name, get(control._defaultValues, name, props.defaultValue)),
219
+ exact: !isArrayField,
214
220
  });
215
221
  const formState = useFormState({
216
222
  control,
@@ -229,7 +235,7 @@ function useController(props) {
229
235
  updateMounted(name, true);
230
236
  return () => {
231
237
  const _shouldUnregisterField = control._options.shouldUnregister || shouldUnregister;
232
- if (isNameInFieldArray(control._names.array, name)
238
+ if (isArrayField
233
239
  ? _shouldUnregisterField && !control._stateFlags.action
234
240
  : _shouldUnregisterField) {
235
241
  control.unregister(name, { keepDefaultValue: true });
@@ -238,7 +244,7 @@ function useController(props) {
238
244
  updateMounted(name, false);
239
245
  }
240
246
  };
241
- }, [name, control, shouldUnregister]);
247
+ }, [name, control, isArrayField, shouldUnregister]);
242
248
  return {
243
249
  field: {
244
250
  onChange: (event) => {
@@ -253,7 +259,7 @@ function useController(props) {
253
259
  onBlur: () => {
254
260
  registerProps.onBlur({
255
261
  target: {
256
- value,
262
+ value: get(control._formValues, name),
257
263
  name: name,
258
264
  },
259
265
  type: EVENTS.BLUR,
@@ -341,6 +347,12 @@ var getFocusFieldName = (name, index, options = {}) => options.shouldFocus || is
341
347
  `${name}.${isUndefined(options.focusIndex) ? index : options.focusIndex}.`
342
348
  : '';
343
349
 
350
+ var isWatched = (name, _names, isBlurEvent) => !isBlurEvent &&
351
+ (_names.watchAll ||
352
+ _names.watch.has(name) ||
353
+ [..._names.watch].some((watchName) => name.startsWith(watchName) &&
354
+ /^\.\w+/.test(name.slice(watchName.length))));
355
+
344
356
  var mapCurrentIds = (values, _fieldIds, keyName) => values.map((value, index) => {
345
357
  const output = _fieldIds.current[index];
346
358
  return Object.assign(Object.assign({}, value), (output ? { [keyName]: output[keyName] } : {}));
@@ -436,44 +448,44 @@ const useFieldArray = (props) => {
436
448
  const append$1 = (value, options) => {
437
449
  const appendValue = convertToArrayPayload(value);
438
450
  const updatedFieldArrayValuesWithKey = append(mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName), mapIds(appendValue, keyName));
451
+ setFields(updatedFieldArrayValuesWithKey);
439
452
  control._updateFieldArray(name, append, {
440
453
  argA: fillEmptyArray(value),
441
454
  }, updateValues(updatedFieldArrayValuesWithKey));
442
- setFields(updatedFieldArrayValuesWithKey);
443
455
  control._names.focus = getFocusFieldName(name, updatedFieldArrayValuesWithKey.length - appendValue.length, options);
444
456
  };
445
457
  const prepend$1 = (value, options) => {
446
458
  const updatedFieldArrayValuesWithKey = prepend(mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName), mapIds(convertToArrayPayload(value), keyName));
459
+ setFields(updatedFieldArrayValuesWithKey);
447
460
  control._updateFieldArray(name, prepend, {
448
461
  argA: fillEmptyArray(value),
449
462
  }, updateValues(updatedFieldArrayValuesWithKey));
450
- setFields(updatedFieldArrayValuesWithKey);
451
463
  control._names.focus = getFocusFieldName(name, 0, options);
452
464
  };
453
465
  const remove = (index) => {
454
466
  const updatedFieldArrayValuesWithKey = removeArrayAt(mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName), index);
467
+ setFields(updatedFieldArrayValuesWithKey);
455
468
  control._updateFieldArray(name, removeArrayAt, {
456
469
  argA: index,
457
470
  }, updateValues(updatedFieldArrayValuesWithKey));
458
- setFields(updatedFieldArrayValuesWithKey);
459
471
  };
460
472
  const insert$1 = (index, value, options) => {
461
473
  const updatedFieldArrayValuesWithKey = insert(mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName), index, mapIds(convertToArrayPayload(value), keyName));
474
+ setFields(updatedFieldArrayValuesWithKey);
462
475
  control._updateFieldArray(name, insert, {
463
476
  argA: index,
464
477
  argB: fillEmptyArray(value),
465
478
  }, updateValues(updatedFieldArrayValuesWithKey));
466
- setFields(updatedFieldArrayValuesWithKey);
467
479
  control._names.focus = getFocusFieldName(name, index, options);
468
480
  };
469
481
  const swap = (indexA, indexB) => {
470
482
  const updatedFieldArrayValuesWithKey = mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName);
471
483
  swapArrayAt(updatedFieldArrayValuesWithKey, indexA, indexB);
484
+ setFields(updatedFieldArrayValuesWithKey);
472
485
  control._updateFieldArray(name, swapArrayAt, {
473
486
  argA: indexA,
474
487
  argB: indexB,
475
488
  }, updateValues(updatedFieldArrayValuesWithKey), false);
476
- setFields(updatedFieldArrayValuesWithKey);
477
489
  };
478
490
  const move = (from, to) => {
479
491
  const updatedFieldArrayValuesWithKey = mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName);
@@ -488,30 +500,20 @@ const useFieldArray = (props) => {
488
500
  const updatedFieldArrayValuesWithKey = mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName);
489
501
  const updatedFieldArrayValues = updateAt(updatedFieldArrayValuesWithKey, index, value);
490
502
  _fieldIds.current = mapIds(updatedFieldArrayValues, keyName);
503
+ setFields(_fieldIds.current);
491
504
  control._updateFieldArray(name, updateAt, {
492
505
  argA: index,
493
506
  argB: value,
494
507
  }, updateValues(_fieldIds.current), true, false);
495
- setFields(_fieldIds.current);
496
508
  };
497
509
  const replace = (value) => {
498
510
  const updatedFieldArrayValuesWithKey = mapIds(convertToArrayPayload(value), keyName);
499
- control._updateFieldArray(name, () => updatedFieldArrayValuesWithKey, {}, updateValues(updatedFieldArrayValuesWithKey), true, false);
500
511
  setFields(updatedFieldArrayValuesWithKey);
512
+ control._updateFieldArray(name, () => updatedFieldArrayValuesWithKey, {}, updateValues(updatedFieldArrayValuesWithKey), true, false);
501
513
  };
502
514
  React.useEffect(() => {
503
515
  control._stateFlags.action = false;
504
- if (control._names.watchAll) {
505
- control._subjects.state.next({});
506
- }
507
- else {
508
- for (const watchField of control._names.watch) {
509
- if (name.startsWith(watchField)) {
510
- control._subjects.state.next({});
511
- break;
512
- }
513
- }
514
- }
516
+ isWatched(name, control._names) && control._subjects.state.next({});
515
517
  if (_actioned.current) {
516
518
  control._executeSchema([name]).then((result) => {
517
519
  const error = get(result.errors, name);
@@ -553,8 +555,6 @@ const useFieldArray = (props) => {
553
555
  };
554
556
  };
555
557
 
556
- var isFunction = (value) => typeof value === 'function';
557
-
558
558
  function cloneObject(data) {
559
559
  let copy;
560
560
  const isArray = Array.isArray(data);
@@ -1108,10 +1108,6 @@ function createFormControl(props = {}) {
1108
1108
  clearTimeout(timer);
1109
1109
  timer = window.setTimeout(() => callback(...args), wait);
1110
1110
  };
1111
- const isFieldWatched = (name, isBlurEvent) => !isBlurEvent &&
1112
- (_names.watchAll ||
1113
- _names.watch.has(name) ||
1114
- _names.watch.has((name.match(/\w+/) || [])[0]));
1115
1111
  const _updateValid = async (shouldSkipRender) => {
1116
1112
  let isValid = false;
1117
1113
  if (_proxyFormState.isValid) {
@@ -1380,7 +1376,7 @@ function createFormControl(props = {}) {
1380
1376
  ? setValues(name, value, options)
1381
1377
  : setFieldValue(name, value, options);
1382
1378
  }
1383
- isFieldWatched(name) && _subjects.state.next({});
1379
+ isWatched(name, _names) && _subjects.state.next({});
1384
1380
  _subjects.watch.next({
1385
1381
  name,
1386
1382
  });
@@ -1399,7 +1395,7 @@ function createFormControl(props = {}) {
1399
1395
  !get(_formState.errors, name) &&
1400
1396
  !field._f.deps) ||
1401
1397
  skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, validationModeAfterSubmit, validationModeBeforeSubmit);
1402
- const isWatched = isFieldWatched(name, isBlurEvent);
1398
+ const watched = isWatched(name, _names, isBlurEvent);
1403
1399
  if (isBlurEvent) {
1404
1400
  field._f.onBlur && field._f.onBlur(event);
1405
1401
  }
@@ -1408,7 +1404,7 @@ function createFormControl(props = {}) {
1408
1404
  }
1409
1405
  set(_formValues, name, fieldValue);
1410
1406
  const fieldState = updateTouchAndDirty(name, fieldValue, isBlurEvent, false);
1411
- const shouldRender = !isEmptyObject(fieldState) || isWatched;
1407
+ const shouldRender = !isEmptyObject(fieldState) || watched;
1412
1408
  !isBlurEvent &&
1413
1409
  _subjects.watch.next({
1414
1410
  name,
@@ -1416,9 +1412,9 @@ function createFormControl(props = {}) {
1416
1412
  });
1417
1413
  if (shouldSkipValidation) {
1418
1414
  return (shouldRender &&
1419
- _subjects.state.next(Object.assign({ name }, (isWatched ? {} : fieldState))));
1415
+ _subjects.state.next(Object.assign({ name }, (watched ? {} : fieldState))));
1420
1416
  }
1421
- !isBlurEvent && isWatched && _subjects.state.next({});
1417
+ !isBlurEvent && watched && _subjects.state.next({});
1422
1418
  validateFields[name] = validateFields[name] ? +1 : 1;
1423
1419
  _proxyFormState.isValidating &&
1424
1420
  _subjects.state.next({
@@ -1832,9 +1828,9 @@ function useForm(props = {}) {
1832
1828
  const control = _formControl.current.control;
1833
1829
  useSubscribe({
1834
1830
  subject: control._subjects.state,
1835
- callback: (formState) => {
1836
- if (shouldRenderFormState(formState, control._proxyFormState, true)) {
1837
- control._formState = Object.assign(Object.assign({}, control._formState), formState);
1831
+ callback: (value) => {
1832
+ if (shouldRenderFormState(value, control._proxyFormState, true)) {
1833
+ control._formState = Object.assign(Object.assign({}, control._formState), value);
1838
1834
  updateFormState(Object.assign({}, control._formState));
1839
1835
  }
1840
1836
  },