react-hook-form 7.19.3 → 7.20.1

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);
@@ -177,47 +169,18 @@ function generateWatchOutput(names, _names, formValues, isGlobal) {
177
169
  return formValues;
178
170
  }
179
171
 
180
- var isKey = (value) => /^\w*$/.test(value);
181
-
182
- var stringToPath = (input) => compact(input.replace(/["|']|\]/g, '').split(/\.|\[/));
183
-
184
- function set(object, path, value) {
185
- let index = -1;
186
- const tempPath = isKey(path) ? [path] : stringToPath(path);
187
- const length = tempPath.length;
188
- const lastIndex = length - 1;
189
- while (++index < length) {
190
- const key = tempPath[index];
191
- let newValue = value;
192
- if (index !== lastIndex) {
193
- const objValue = object[key];
194
- newValue =
195
- isObject(objValue) || Array.isArray(objValue)
196
- ? objValue
197
- : !isNaN(+tempPath[index + 1])
198
- ? []
199
- : {};
200
- }
201
- object[key] = newValue;
202
- object = object[key];
203
- }
204
- return object;
205
- }
206
-
207
172
  function useWatch(props) {
208
173
  const methods = useFormContext();
209
- const { control = methods.control, name, defaultValue, disabled, } = props || {};
174
+ const { control = methods.control, name, defaultValue, disabled, exact, } = props || {};
210
175
  const _name = React.useRef(name);
211
176
  _name.current = name;
212
177
  useSubscribe({
213
178
  disabled,
214
179
  subject: control._subjects.watch,
215
180
  callback: (formState) => {
216
- if (shouldSubscribeByName(_name.current, formState.name)) {
181
+ if (shouldSubscribeByName(_name.current, formState.name, exact)) {
217
182
  const fieldValues = generateWatchOutput(_name.current, control._names, formState.values || control._formValues);
218
- updateValue(isObject(fieldValues) &&
219
- !(isString(_name.current) &&
220
- get(control._fields, _name.current, {})._f)
183
+ updateValue(isUndefined(_name.current)
221
184
  ? Object.assign({}, fieldValues) : Array.isArray(fieldValues)
222
185
  ? [...fieldValues]
223
186
  : fieldValues);
@@ -236,10 +199,12 @@ function useWatch(props) {
236
199
  function useController(props) {
237
200
  const methods = useFormContext();
238
201
  const { name, control = methods.control, shouldUnregister } = props;
202
+ const isArrayField = isNameInFieldArray(control._names.array, name);
239
203
  const value = useWatch({
240
204
  control,
241
205
  name,
242
206
  defaultValue: get(control._formValues, name, get(control._defaultValues, name, props.defaultValue)),
207
+ exact: !isArrayField,
243
208
  });
244
209
  const formState = useFormState({
245
210
  control,
@@ -258,7 +223,7 @@ function useController(props) {
258
223
  updateMounted(name, true);
259
224
  return () => {
260
225
  const _shouldUnregisterField = control._options.shouldUnregister || shouldUnregister;
261
- if (isNameInFieldArray(control._names.array, name)
226
+ if (isArrayField
262
227
  ? _shouldUnregisterField && !control._stateFlags.action
263
228
  : _shouldUnregisterField) {
264
229
  control.unregister(name, { keepDefaultValue: true });
@@ -267,7 +232,7 @@ function useController(props) {
267
232
  updateMounted(name, false);
268
233
  }
269
234
  };
270
- }, [name, control, shouldUnregister]);
235
+ }, [name, control, isArrayField, shouldUnregister]);
271
236
  return {
272
237
  field: {
273
238
  onChange: (event) => {
@@ -282,7 +247,7 @@ function useController(props) {
282
247
  onBlur: () => {
283
248
  registerProps.onBlur({
284
249
  target: {
285
- value,
250
+ value: get(control._formValues, name),
286
251
  name: name,
287
252
  },
288
253
  type: EVENTS.BLUR,
@@ -316,6 +281,33 @@ const Controller = (props) => props.render(useController(props));
316
281
  var appendErrors = (name, validateAllFieldCriteria, errors, type, message) => validateAllFieldCriteria
317
282
  ? Object.assign(Object.assign({}, errors[name]), { types: Object.assign(Object.assign({}, (errors[name] && errors[name].types ? errors[name].types : {})), { [type]: message || true }) }) : {};
318
283
 
284
+ var isKey = (value) => /^\w*$/.test(value);
285
+
286
+ var stringToPath = (input) => compact(input.replace(/["|']|\]/g, '').split(/\.|\[/));
287
+
288
+ function set(object, path, value) {
289
+ let index = -1;
290
+ const tempPath = isKey(path) ? [path] : stringToPath(path);
291
+ const length = tempPath.length;
292
+ const lastIndex = length - 1;
293
+ while (++index < length) {
294
+ const key = tempPath[index];
295
+ let newValue = value;
296
+ if (index !== lastIndex) {
297
+ const objValue = object[key];
298
+ newValue =
299
+ isObject(objValue) || Array.isArray(objValue)
300
+ ? objValue
301
+ : !isNaN(+tempPath[index + 1])
302
+ ? []
303
+ : {};
304
+ }
305
+ object[key] = newValue;
306
+ object = object[key];
307
+ }
308
+ return object;
309
+ }
310
+
319
311
  const focusFieldBy = (fields, callback, fieldsNames) => {
320
312
  for (const key of fieldsNames || Object.keys(fields)) {
321
313
  const field = get(fields, key);
@@ -343,6 +335,12 @@ var getFocusFieldName = (name, index, options = {}) => options.shouldFocus || is
343
335
  `${name}.${isUndefined(options.focusIndex) ? index : options.focusIndex}.`
344
336
  : '';
345
337
 
338
+ var isWatched = (name, _names, isBlurEvent) => !isBlurEvent &&
339
+ (_names.watchAll ||
340
+ _names.watch.has(name) ||
341
+ [..._names.watch].some((watchName) => name.startsWith(watchName) &&
342
+ /^\.\w+/.test(name.slice(watchName.length))));
343
+
346
344
  var mapCurrentIds = (values, _fieldIds, keyName) => values.map((value, index) => {
347
345
  const output = _fieldIds.current[index];
348
346
  return Object.assign(Object.assign({}, value), (output ? { [keyName]: output[keyName] } : {}));
@@ -433,12 +431,12 @@ const useFieldArray = (props) => {
433
431
  const updatedFieldArrayValues = omitKeys(updatedFieldArrayValuesWithKey, keyName);
434
432
  _actioned.current = true;
435
433
  set(control._formValues, name, updatedFieldArrayValues);
436
- setFields(updatedFieldArrayValuesWithKey);
437
434
  return updatedFieldArrayValues;
438
435
  }, [control, name, keyName]);
439
436
  const append$1 = (value, options) => {
440
437
  const appendValue = convertToArrayPayload(value);
441
438
  const updatedFieldArrayValuesWithKey = append(mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName), mapIds(appendValue, keyName));
439
+ setFields(updatedFieldArrayValuesWithKey);
442
440
  control._updateFieldArray(name, append, {
443
441
  argA: fillEmptyArray(value),
444
442
  }, updateValues(updatedFieldArrayValuesWithKey));
@@ -446,6 +444,7 @@ const useFieldArray = (props) => {
446
444
  };
447
445
  const prepend$1 = (value, options) => {
448
446
  const updatedFieldArrayValuesWithKey = prepend(mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName), mapIds(convertToArrayPayload(value), keyName));
447
+ setFields(updatedFieldArrayValuesWithKey);
449
448
  control._updateFieldArray(name, prepend, {
450
449
  argA: fillEmptyArray(value),
451
450
  }, updateValues(updatedFieldArrayValuesWithKey));
@@ -453,12 +452,14 @@ const useFieldArray = (props) => {
453
452
  };
454
453
  const remove = (index) => {
455
454
  const updatedFieldArrayValuesWithKey = removeArrayAt(mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName), index);
455
+ setFields(updatedFieldArrayValuesWithKey);
456
456
  control._updateFieldArray(name, removeArrayAt, {
457
457
  argA: index,
458
458
  }, updateValues(updatedFieldArrayValuesWithKey));
459
459
  };
460
460
  const insert$1 = (index, value, options) => {
461
461
  const updatedFieldArrayValuesWithKey = insert(mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName), index, mapIds(convertToArrayPayload(value), keyName));
462
+ setFields(updatedFieldArrayValuesWithKey);
462
463
  control._updateFieldArray(name, insert, {
463
464
  argA: index,
464
465
  argB: fillEmptyArray(value),
@@ -468,6 +469,7 @@ const useFieldArray = (props) => {
468
469
  const swap = (indexA, indexB) => {
469
470
  const updatedFieldArrayValuesWithKey = mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName);
470
471
  swapArrayAt(updatedFieldArrayValuesWithKey, indexA, indexB);
472
+ setFields(updatedFieldArrayValuesWithKey);
471
473
  control._updateFieldArray(name, swapArrayAt, {
472
474
  argA: indexA,
473
475
  argB: indexB,
@@ -480,11 +482,13 @@ const useFieldArray = (props) => {
480
482
  argA: from,
481
483
  argB: to,
482
484
  }, updateValues(updatedFieldArrayValuesWithKey), false);
485
+ setFields(updatedFieldArrayValuesWithKey);
483
486
  };
484
487
  const update = (index, value) => {
485
488
  const updatedFieldArrayValuesWithKey = mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName);
486
489
  const updatedFieldArrayValues = updateAt(updatedFieldArrayValuesWithKey, index, value);
487
490
  _fieldIds.current = mapIds(updatedFieldArrayValues, keyName);
491
+ setFields(_fieldIds.current);
488
492
  control._updateFieldArray(name, updateAt, {
489
493
  argA: index,
490
494
  argB: value,
@@ -492,21 +496,12 @@ const useFieldArray = (props) => {
492
496
  };
493
497
  const replace = (value) => {
494
498
  const updatedFieldArrayValuesWithKey = mapIds(convertToArrayPayload(value), keyName);
499
+ setFields(updatedFieldArrayValuesWithKey);
495
500
  control._updateFieldArray(name, () => updatedFieldArrayValuesWithKey, {}, updateValues(updatedFieldArrayValuesWithKey), true, false);
496
501
  };
497
502
  React.useEffect(() => {
498
503
  control._stateFlags.action = false;
499
- if (control._names.watchAll) {
500
- control._subjects.state.next({});
501
- }
502
- else {
503
- for (const watchField of control._names.watch) {
504
- if (name.startsWith(watchField)) {
505
- control._subjects.state.next({});
506
- break;
507
- }
508
- }
509
- }
504
+ isWatched(name, control._names) && control._subjects.state.next({});
510
505
  if (_actioned.current) {
511
506
  control._executeSchema([name]).then((result) => {
512
507
  const error = get(result.errors, name);
@@ -1103,10 +1098,6 @@ function createFormControl(props = {}) {
1103
1098
  clearTimeout(timer);
1104
1099
  timer = window.setTimeout(() => callback(...args), wait);
1105
1100
  };
1106
- const isFieldWatched = (name, isBlurEvent) => !isBlurEvent &&
1107
- (_names.watchAll ||
1108
- _names.watch.has(name) ||
1109
- _names.watch.has((name.match(/\w+/) || [])[0]));
1110
1101
  const _updateValid = async (shouldSkipRender) => {
1111
1102
  let isValid = false;
1112
1103
  if (_proxyFormState.isValid) {
@@ -1375,7 +1366,7 @@ function createFormControl(props = {}) {
1375
1366
  ? setValues(name, value, options)
1376
1367
  : setFieldValue(name, value, options);
1377
1368
  }
1378
- isFieldWatched(name) && _subjects.state.next({});
1369
+ isWatched(name, _names) && _subjects.state.next({});
1379
1370
  _subjects.watch.next({
1380
1371
  name,
1381
1372
  });
@@ -1394,7 +1385,7 @@ function createFormControl(props = {}) {
1394
1385
  !get(_formState.errors, name) &&
1395
1386
  !field._f.deps) ||
1396
1387
  skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, validationModeAfterSubmit, validationModeBeforeSubmit);
1397
- const isWatched = isFieldWatched(name, isBlurEvent);
1388
+ const watched = isWatched(name, _names, isBlurEvent);
1398
1389
  if (isBlurEvent) {
1399
1390
  field._f.onBlur && field._f.onBlur(event);
1400
1391
  }
@@ -1403,7 +1394,7 @@ function createFormControl(props = {}) {
1403
1394
  }
1404
1395
  set(_formValues, name, fieldValue);
1405
1396
  const fieldState = updateTouchAndDirty(name, fieldValue, isBlurEvent, false);
1406
- const shouldRender = !isEmptyObject(fieldState) || isWatched;
1397
+ const shouldRender = !isEmptyObject(fieldState) || watched;
1407
1398
  !isBlurEvent &&
1408
1399
  _subjects.watch.next({
1409
1400
  name,
@@ -1411,9 +1402,9 @@ function createFormControl(props = {}) {
1411
1402
  });
1412
1403
  if (shouldSkipValidation) {
1413
1404
  return (shouldRender &&
1414
- _subjects.state.next(Object.assign({ name }, (isWatched ? {} : fieldState))));
1405
+ _subjects.state.next(Object.assign({ name }, (watched ? {} : fieldState))));
1415
1406
  }
1416
- !isBlurEvent && isWatched && _subjects.state.next({});
1407
+ !isBlurEvent && watched && _subjects.state.next({});
1417
1408
  validateFields[name] = validateFields[name] ? +1 : 1;
1418
1409
  _proxyFormState.isValidating &&
1419
1410
  _subjects.state.next({
@@ -1827,9 +1818,9 @@ function useForm(props = {}) {
1827
1818
  const control = _formControl.current.control;
1828
1819
  useSubscribe({
1829
1820
  subject: control._subjects.state,
1830
- callback: (formState) => {
1831
- if (shouldRenderFormState(formState, control._proxyFormState, true)) {
1832
- control._formState = Object.assign(Object.assign({}, control._formState), formState);
1821
+ callback: (value) => {
1822
+ if (shouldRenderFormState(value, control._proxyFormState, true)) {
1823
+ control._formState = Object.assign(Object.assign({}, control._formState), value);
1833
1824
  updateFormState(Object.assign({}, control._formState));
1834
1825
  }
1835
1826
  },