react-hook-form 7.18.0 → 7.19.0-next.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.
package/dist/index.esm.js CHANGED
@@ -105,37 +105,35 @@ var convertToArrayPayload = (value) => (Array.isArray(value) ? value : [value]);
105
105
 
106
106
  var shouldSubscribeByName = (name, signalName) => !name ||
107
107
  !signalName ||
108
+ name === signalName ||
108
109
  convertToArrayPayload(name).some((currentName) => currentName &&
109
110
  (currentName.startsWith(signalName) ||
110
111
  signalName.startsWith(currentName)));
111
112
 
112
- const tearDown = (_unsubscribe) => {
113
- if (_unsubscribe.current) {
114
- _unsubscribe.current.unsubscribe();
115
- _unsubscribe.current = undefined;
113
+ const tearDown = (_subscription) => {
114
+ if (_subscription.current) {
115
+ _subscription.current.unsubscribe();
116
+ _subscription.current = undefined;
116
117
  }
117
118
  };
118
- const updateSubscriptionProps = ({ _unsubscribe, props }) => () => {
119
+ const updateSubscriptionProps = ({ _subscription, props }) => {
119
120
  if (props.disabled) {
120
- tearDown(_unsubscribe);
121
+ tearDown(_subscription);
121
122
  }
122
- else if (!_unsubscribe.current) {
123
- _unsubscribe.current = props.subject.subscribe({
123
+ else if (!_subscription.current) {
124
+ _subscription.current = props.subject.subscribe({
124
125
  next: props.callback,
125
126
  });
126
127
  }
127
128
  };
128
129
  function useSubscribe(props) {
129
- const _unsubscribe = React.useRef();
130
- const _updateSubscription = React.useRef(() => { });
131
- _updateSubscription.current = updateSubscriptionProps({
132
- _unsubscribe,
130
+ const _subscription = React.useRef();
131
+ updateSubscriptionProps({
132
+ _subscription,
133
133
  props,
134
134
  });
135
- !props.skipEarlySubscription && _updateSubscription.current();
136
135
  React.useEffect(() => {
137
- _updateSubscription.current();
138
- return () => tearDown(_unsubscribe);
136
+ return () => tearDown(_subscription);
139
137
  }, []);
140
138
  }
141
139
 
@@ -159,35 +157,75 @@ function useFormState(props) {
159
157
  shouldRenderFormState(formState, _localProxyFormState.current) &&
160
158
  updateFormState(Object.assign(Object.assign({}, control._formState), formState)),
161
159
  subject: control._subjects.state,
162
- skipEarlySubscription: true,
163
160
  });
164
161
  return getProxyFormState(formState, control._proxyFormState, _localProxyFormState.current, false);
165
162
  }
166
163
 
164
+ var isString = (value) => typeof value === 'string';
165
+
166
+ function generateWatchOutput(names, _names, formValues, isGlobal) {
167
+ const isArray = Array.isArray(names);
168
+ if (isString(names)) {
169
+ isGlobal && _names.watch.add(names);
170
+ return get(formValues, names);
171
+ }
172
+ if (isArray) {
173
+ return names.map((fieldName) => (isGlobal && _names.watch.add(fieldName),
174
+ get(formValues, fieldName)));
175
+ }
176
+ isGlobal && (_names.watchAll = true);
177
+ return formValues;
178
+ }
179
+
180
+ function useWatch(props) {
181
+ const methods = useFormContext();
182
+ const { control = methods.control, name, defaultValue, disabled, } = props || {};
183
+ const _name = React.useRef(name);
184
+ _name.current = name;
185
+ useSubscribe({
186
+ disabled,
187
+ subject: control._subjects.watch,
188
+ callback: (formState) => {
189
+ if (shouldSubscribeByName(_name.current, formState.name)) {
190
+ const fieldValues = generateWatchOutput(_name.current, control._names, control._formValues);
191
+ updateValue(isObject(fieldValues)
192
+ ? Object.assign({}, fieldValues) : Array.isArray(fieldValues)
193
+ ? [...fieldValues]
194
+ : fieldValues);
195
+ }
196
+ },
197
+ });
198
+ const [value, updateValue] = React.useState(isUndefined(defaultValue)
199
+ ? control._getWatch(name)
200
+ : defaultValue);
201
+ React.useEffect(() => {
202
+ control._removeUnmounted();
203
+ });
204
+ return value;
205
+ }
206
+
167
207
  function useController(props) {
168
208
  const methods = useFormContext();
169
209
  const { name, control = methods.control, shouldUnregister } = props;
170
- const [value, setInputStateValue] = React.useState(get(control._formValues, name, get(control._defaultValues, name, props.defaultValue)));
210
+ const value = useWatch({
211
+ control,
212
+ name,
213
+ defaultValue: get(control._formValues, name, get(control._defaultValues, name, props.defaultValue)),
214
+ });
171
215
  const formState = useFormState({
172
- control: control || methods.control,
216
+ control,
173
217
  name,
174
218
  });
175
219
  const _name = React.useRef(name);
176
220
  _name.current = name;
177
- useSubscribe({
178
- subject: control._subjects.control,
179
- callback: (data) => (!data.name || _name.current === data.name) &&
180
- setInputStateValue(get(data.values, _name.current)),
181
- skipEarlySubscription: true,
182
- });
183
221
  const registerProps = control.register(name, Object.assign(Object.assign({}, props.rules), { value }));
184
- const updateMounted = React.useCallback((name, value) => {
185
- const field = get(control._fields, name);
186
- if (field) {
187
- field._f.mount = value;
188
- }
189
- }, [control]);
190
222
  React.useEffect(() => {
223
+ const updateMounted = (name, value) => {
224
+ const field = get(control._fields, name);
225
+ if (field) {
226
+ field._f.mount = value;
227
+ }
228
+ };
191
229
  updateMounted(name, true);
192
230
  return () => {
193
231
  const _shouldUnregisterField = control._options.shouldUnregister || shouldUnregister;
@@ -200,15 +238,13 @@ function useController(props) {
200
238
  updateMounted(name, false);
201
239
  }
202
240
  };
203
- }, [name, control, shouldUnregister, updateMounted]);
241
+ }, [name, control, shouldUnregister]);
204
242
  return {
205
243
  field: {
206
244
  onChange: (event) => {
207
- const value = getControllerValue(event);
208
- setInputStateValue(value);
209
245
  registerProps.onChange({
210
246
  target: {
211
- value,
247
+ value: getControllerValue(event),
212
248
  name: name,
213
249
  },
214
250
  type: EVENTS.CHANGE,
@@ -379,6 +415,7 @@ const useFieldArray = (props) => {
379
415
  const [fields, setFields] = React.useState(mapIds(control._getFieldArray(name), keyName));
380
416
  const _fieldIds = React.useRef(fields);
381
417
  const _name = React.useRef(name);
418
+ const _actioned = React.useRef(false);
382
419
  _name.current = name;
383
420
  _fieldIds.current = fields;
384
421
  control._names.array.add(name);
@@ -389,10 +426,10 @@ const useFieldArray = (props) => {
389
426
  }
390
427
  },
391
428
  subject: control._subjects.array,
392
- skipEarlySubscription: true,
393
429
  });
394
430
  const updateValues = React.useCallback((updatedFieldArrayValuesWithKey) => {
395
431
  const updatedFieldArrayValues = omitKeys(updatedFieldArrayValuesWithKey, keyName);
432
+ _actioned.current = true;
396
433
  set(control._formValues, name, updatedFieldArrayValues);
397
434
  setFields(updatedFieldArrayValuesWithKey);
398
435
  return updatedFieldArrayValues;
@@ -468,15 +505,17 @@ const useFieldArray = (props) => {
468
505
  }
469
506
  }
470
507
  }
471
- control._executeSchema([name]).then((result) => {
472
- const error = get(result.errors, name);
473
- if (error && error.type && !get(control._formState.errors, name)) {
474
- set(control._formState.errors, name, error);
475
- control._subjects.state.next({
476
- errors: control._formState.errors,
477
- });
478
- }
479
- });
508
+ if (_actioned.current) {
509
+ control._executeSchema([name]).then((result) => {
510
+ const error = get(result.errors, name);
511
+ if (error && error.type && !get(control._formState.errors, name)) {
512
+ set(control._formState.errors, name, error);
513
+ control._subjects.state.next({
514
+ errors: control._formState.errors,
515
+ });
516
+ }
517
+ });
518
+ }
480
519
  control._subjects.watch.next({
481
520
  name,
482
521
  values: control._formValues,
@@ -534,34 +573,6 @@ function cloneObject(data) {
534
573
  return copy;
535
574
  }
536
575
 
537
- function createSubscription() {
538
- let tearDowns = [];
539
- const add = (tearDown) => {
540
- tearDowns.push(tearDown);
541
- };
542
- const unsubscribe = () => {
543
- for (const teardown of tearDowns) {
544
- teardown();
545
- }
546
- tearDowns = [];
547
- };
548
- return {
549
- add,
550
- unsubscribe,
551
- };
552
- }
553
- function createSubscriber(observer, subscription) {
554
- let closed = false;
555
- subscription.add(() => (closed = true));
556
- const next = (value) => {
557
- if (!closed) {
558
- observer.next(value);
559
- }
560
- };
561
- return {
562
- next,
563
- };
564
- }
565
576
  function createSubject() {
566
577
  let _observers = [];
567
578
  const next = (value) => {
@@ -570,10 +581,12 @@ function createSubject() {
570
581
  }
571
582
  };
572
583
  const subscribe = (observer) => {
573
- const subscription = createSubscription();
574
- const subscriber = createSubscriber(observer, subscription);
575
- _observers.push(subscriber);
576
- return subscription;
584
+ _observers.push(observer);
585
+ return {
586
+ unsubscribe: () => {
587
+ _observers = _observers.filter((o) => o !== observer);
588
+ },
589
+ };
577
590
  };
578
591
  const unsubscribe = () => {
579
592
  _observers = [];
@@ -641,8 +654,6 @@ var isRadioInput = (element) => element.type === 'radio';
641
654
 
642
655
  var isRadioOrCheckboxFunction = (ref) => isRadioInput(ref) || isCheckBoxInput(ref);
643
656
 
644
- var isString = (value) => typeof value === 'string';
645
-
646
657
  var isWeb = typeof window !== 'undefined' &&
647
658
  typeof window.HTMLElement !== 'undefined' &&
648
659
  typeof document !== 'undefined';
@@ -1080,7 +1091,6 @@ function createFormControl(props = {}) {
1080
1091
  };
1081
1092
  const _subjects = {
1082
1093
  watch: createSubject(),
1083
- control: createSubject(),
1084
1094
  array: createSubject(),
1085
1095
  state: createSubject(),
1086
1096
  };
@@ -1285,16 +1295,10 @@ function createFormControl(props = {}) {
1285
1295
  : isString(names)
1286
1296
  ? { [names]: defaultValue }
1287
1297
  : defaultValue));
1288
- if (names) {
1289
- const result = convertToArrayPayload(names).map((fieldName) => (isGlobal && _names.watch.add(fieldName),
1290
- get(fieldValues, fieldName)));
1291
- return Array.isArray(names) ? result : result[0];
1292
- }
1293
- isGlobal && (_names.watchAll = true);
1294
- return fieldValues;
1298
+ return generateWatchOutput(names, _names, fieldValues, isGlobal);
1295
1299
  };
1296
1300
  const _getFieldArray = (name) => get(_stateFlags.mount ? _formValues : _defaultValues, name, props.shouldUnregister ? get(_defaultValues, name, []) : []);
1297
- const setFieldValue = (name, value, options = {}, shouldRender) => {
1301
+ const setFieldValue = (name, value, options = {}) => {
1298
1302
  const field = get(_fields, name);
1299
1303
  let fieldValue = value;
1300
1304
  if (field) {
@@ -1326,11 +1330,6 @@ function createFormControl(props = {}) {
1326
1330
  else {
1327
1331
  fieldReference.ref.value = fieldValue;
1328
1332
  }
1329
- shouldRender &&
1330
- _subjects.control.next({
1331
- values: _formValues,
1332
- name,
1333
- });
1334
1333
  }
1335
1334
  }
1336
1335
  (options.shouldDirty || options.shouldTouch) &&
@@ -1347,7 +1346,7 @@ function createFormControl(props = {}) {
1347
1346
  (field && !field._f)) &&
1348
1347
  !isDateObject(fieldValue)
1349
1348
  ? setValues(fieldName, fieldValue, options)
1350
- : setFieldValue(fieldName, fieldValue, options, true);
1349
+ : setFieldValue(fieldName, fieldValue, options);
1351
1350
  }
1352
1351
  };
1353
1352
  const setValue = (name, value, options = {}) => {
@@ -1372,7 +1371,7 @@ function createFormControl(props = {}) {
1372
1371
  else {
1373
1372
  field && !field._f && !isNullOrUndefined(value)
1374
1373
  ? setValues(name, value, options)
1375
- : setFieldValue(name, value, options, true);
1374
+ : setFieldValue(name, value, options);
1376
1375
  }
1377
1376
  isFieldWatched(name) && _subjects.state.next({});
1378
1377
  _subjects.watch.next({
@@ -1526,7 +1525,8 @@ function createFormControl(props = {}) {
1526
1525
  _f: Object.assign(Object.assign(Object.assign({}, (field && field._f ? field._f : { ref: { name } })), { name, mount: true }), options),
1527
1526
  });
1528
1527
  _names.mount.add(name);
1529
- !isUndefined(options.value) && set(_formValues, name, options.value);
1528
+ !isUndefined(options.value) &&
1529
+ set(_formValues, name, get(_formValues, name, options.value));
1530
1530
  field
1531
1531
  ? isBoolean(options.disabled) &&
1532
1532
  set(_formValues, name, options.disabled
@@ -1624,10 +1624,35 @@ function createFormControl(props = {}) {
1624
1624
  });
1625
1625
  }
1626
1626
  };
1627
+ const resetField = (name, options = {}) => {
1628
+ if (isUndefined(options.defaultValue)) {
1629
+ setValue(name, get(_defaultValues, name));
1630
+ }
1631
+ else {
1632
+ setValue(name, options.defaultValue);
1633
+ set(_defaultValues, name, options.defaultValue);
1634
+ }
1635
+ if (!options.keepTouched) {
1636
+ unset(_formState.touchedFields, name);
1637
+ }
1638
+ if (!options.keepDirty) {
1639
+ unset(_formState.dirtyFields, name);
1640
+ _formState.isDirty = options.defaultValue
1641
+ ? _getDirty(name, get(_defaultValues, name))
1642
+ : _getDirty();
1643
+ }
1644
+ if (!options.keepError) {
1645
+ unset(_formState.errors, name);
1646
+ _proxyFormState.isValid && _updateValid();
1647
+ }
1648
+ _subjects.state.next(Object.assign({}, _formState));
1649
+ };
1627
1650
  const reset = (formValues, keepStateOptions = {}) => {
1628
- const hasUpdatedFormValues = !isEmptyObject(formValues);
1629
1651
  const updatedValues = formValues || _defaultValues;
1630
1652
  const cloneUpdatedValues = cloneObject(updatedValues);
1653
+ const values = !isEmptyObject(formValues)
1654
+ ? cloneUpdatedValues
1655
+ : _defaultValues;
1631
1656
  if (!keepStateOptions.keepDefaultValues) {
1632
1657
  _defaultValues = updatedValues;
1633
1658
  }
@@ -1654,12 +1679,11 @@ function createFormControl(props = {}) {
1654
1679
  : {}
1655
1680
  : cloneUpdatedValues;
1656
1681
  _fields = {};
1657
- _subjects.control.next({
1658
- values: hasUpdatedFormValues ? cloneUpdatedValues : _defaultValues,
1682
+ _subjects.watch.next({
1683
+ values,
1659
1684
  });
1660
- _subjects.watch.next({});
1661
1685
  _subjects.array.next({
1662
- values: cloneUpdatedValues,
1686
+ values,
1663
1687
  });
1664
1688
  }
1665
1689
  _names = {
@@ -1767,6 +1791,7 @@ function createFormControl(props = {}) {
1767
1791
  setValue,
1768
1792
  getValues,
1769
1793
  reset,
1794
+ resetField,
1770
1795
  clearErrors,
1771
1796
  unregister,
1772
1797
  setError,
@@ -1820,33 +1845,5 @@ function useForm(props = {}) {
1820
1845
  return _formControl.current;
1821
1846
  }
1822
1847
 
1823
- function useWatch(props) {
1824
- const methods = useFormContext();
1825
- const { control = methods.control, name, defaultValue, disabled, } = props || {};
1826
- const _name = React.useRef(name);
1827
- _name.current = name;
1828
- useSubscribe({
1829
- disabled,
1830
- subject: control._subjects.watch,
1831
- callback: (formState) => {
1832
- if (shouldSubscribeByName(_name.current, formState.name)) {
1833
- control._stateFlags.mount = true;
1834
- const fieldValues = control._getWatch(_name.current, defaultValue);
1835
- updateValue(isObject(fieldValues)
1836
- ? Object.assign({}, fieldValues) : Array.isArray(fieldValues)
1837
- ? [...fieldValues]
1838
- : fieldValues);
1839
- }
1840
- },
1841
- });
1842
- const [value, updateValue] = React.useState(isUndefined(defaultValue)
1843
- ? control._getWatch(name)
1844
- : defaultValue);
1845
- React.useEffect(() => {
1846
- control._removeUnmounted();
1847
- });
1848
- return value;
1849
- }
1850
-
1851
1848
  export { Controller, FormProvider, appendErrors, get, set, useController, useFieldArray, useForm, useFormContext, useFormState, useWatch };
1852
1849
  //# sourceMappingURL=index.esm.js.map