react-hook-form 7.39.5 → 7.40.0-next.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.
@@ -122,10 +122,7 @@ const useFormContext = () => React.useContext(HookFormContext);
122
122
  * }
123
123
  * ```
124
124
  */
125
- const FormProvider = (props) => {
126
- const { children, ...data } = props;
127
- return (React.createElement(HookFormContext.Provider, { value: data }, children));
128
- };
125
+ const FormProvider = ({ children, ...data }) => (React.createElement(HookFormContext.Provider, { value: React.useState(data)[0] }, children));
129
126
 
130
127
  var getProxyFormState = (formState, control, localProxyFormState, isRoot = true) => {
131
128
  const result = {
@@ -173,7 +170,7 @@ function useSubscribe(props) {
173
170
  React.useEffect(() => {
174
171
  const subscription = !props.disabled &&
175
172
  _props.current.subject.subscribe({
176
- next: _props.current.callback,
173
+ next: _props.current.next,
177
174
  });
178
175
  return () => {
179
176
  subscription && subscription.unsubscribe();
@@ -228,13 +225,13 @@ function useFormState(props) {
228
225
  _name.current = name;
229
226
  useSubscribe({
230
227
  disabled,
231
- callback: React.useCallback((value) => _mounted.current &&
228
+ next: (value) => _mounted.current &&
232
229
  shouldSubscribeByName(_name.current, value.name, exact) &&
233
230
  shouldRenderFormState(value, _localProxyFormState.current) &&
234
231
  updateFormState({
235
232
  ...control._formState,
236
233
  ...value,
237
- }), [control, exact]),
234
+ }),
238
235
  subject: control._subjects.state,
239
236
  });
240
237
  React.useEffect(() => {
@@ -327,10 +324,14 @@ function useWatch(props) {
327
324
  useSubscribe({
328
325
  disabled,
329
326
  subject: control._subjects.watch,
330
- callback: (formState) => {
327
+ next: (formState) => {
331
328
  if (shouldSubscribeByName(_name.current, formState.name, exact)) {
332
329
  const fieldValues = generateWatchOutput(_name.current, control._names, formState.values || control._formValues);
333
- updateValue(isUndefined(fieldValues) ? defaultValue : cloneObject(fieldValues));
330
+ updateValue(isUndefined(_name.current) || !isUndefined(fieldValues)
331
+ ? cloneObject(fieldValues)
332
+ : isUndefined(fieldValues)
333
+ ? defaultValue
334
+ : fieldValues);
334
335
  }
335
336
  },
336
337
  });
@@ -980,17 +981,16 @@ function useFieldArray(props) {
980
981
  control._names.array.add(name);
981
982
  props.rules &&
982
983
  control.register(name, props.rules);
983
- const callback = React.useCallback(({ values, name: fieldArrayName, }) => {
984
- if (fieldArrayName === _name.current || !fieldArrayName) {
985
- const fieldValues = get(values, _name.current);
986
- if (Array.isArray(fieldValues)) {
987
- setFields(fieldValues);
988
- ids.current = fieldValues.map(generateId);
989
- }
990
- }
991
- }, []);
992
984
  useSubscribe({
993
- callback,
985
+ next: ({ values, name: fieldArrayName, }) => {
986
+ if (fieldArrayName === _name.current || !fieldArrayName) {
987
+ const fieldValues = get(values, _name.current);
988
+ if (Array.isArray(fieldValues)) {
989
+ setFields(fieldValues);
990
+ ids.current = fieldValues.map(generateId);
991
+ }
992
+ }
993
+ },
994
994
  subject: control._subjects.array,
995
995
  });
996
996
  const updateValues = React.useCallback((updatedFieldArrayValues) => {
@@ -1205,8 +1205,8 @@ function deepEqual(object1, object2) {
1205
1205
 
1206
1206
  var isHTMLElement = (value) => {
1207
1207
  const owner = value ? value.ownerDocument : 0;
1208
- const ElementClass = owner && owner.defaultView ? owner.defaultView.HTMLElement : HTMLElement;
1209
- return value instanceof ElementClass;
1208
+ return (value instanceof
1209
+ (owner && owner.defaultView ? owner.defaultView.HTMLElement : HTMLElement));
1210
1210
  };
1211
1211
 
1212
1212
  var isMultipleSelect = (element) => element.type === `select-multiple`;
@@ -1391,6 +1391,7 @@ function createFormControl(props = {}) {
1391
1391
  ...defaultOptions,
1392
1392
  ...props,
1393
1393
  };
1394
+ const shouldCaptureDirtyFields = props.resetOptions && props.resetOptions.keepDirtyValues;
1394
1395
  let _formState = {
1395
1396
  submitCount: 0,
1396
1397
  isDirty: false,
@@ -1404,7 +1405,9 @@ function createFormControl(props = {}) {
1404
1405
  errors: {},
1405
1406
  };
1406
1407
  let _fields = {};
1407
- let _defaultValues = cloneObject(_options.defaultValues) || {};
1408
+ let _defaultValues = isObject(_options.defaultValues)
1409
+ ? cloneObject(_options.defaultValues) || {}
1410
+ : {};
1408
1411
  let _formValues = _options.shouldUnregister
1409
1412
  ? {}
1410
1413
  : cloneObject(_defaultValues);
@@ -1443,11 +1446,10 @@ function createFormControl(props = {}) {
1443
1446
  timer = window.setTimeout(callback, wait);
1444
1447
  };
1445
1448
  const _updateValid = async () => {
1446
- let isValid = false;
1447
1449
  if (_proxyFormState.isValid) {
1448
- isValid = _options.resolver
1450
+ const isValid = _options.resolver
1449
1451
  ? isEmptyObject((await _executeSchema()).errors)
1450
- : await executeBuiltInValidation(_fields, true);
1452
+ : (await executeBuiltInValidation(_fields, true)).valid;
1451
1453
  if (isValid !== _formState.isValid) {
1452
1454
  _formState.isValid = isValid;
1453
1455
  _subjects.state.next({
@@ -1455,7 +1457,6 @@ function createFormControl(props = {}) {
1455
1457
  });
1456
1458
  }
1457
1459
  }
1458
- return isValid;
1459
1460
  };
1460
1461
  const _updateFieldArray = (name, values = [], method, args, shouldSetValues = true, shouldUpdateFieldsAndState = true) => {
1461
1462
  if (args && method) {
@@ -1519,15 +1520,17 @@ function createFormControl(props = {}) {
1519
1520
  _formState.isDirty = output.isDirty = _getDirty();
1520
1521
  shouldUpdateField = isPreviousDirty !== output.isDirty;
1521
1522
  }
1522
- if (_proxyFormState.dirtyFields && (!isBlurEvent || shouldDirty)) {
1523
- isPreviousDirty = get(_formState.dirtyFields, name);
1523
+ if (!isBlurEvent || shouldDirty) {
1524
1524
  const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
1525
+ isPreviousDirty = get(_formState.dirtyFields, name);
1525
1526
  isCurrentFieldPristine
1526
1527
  ? unset(_formState.dirtyFields, name)
1527
1528
  : set(_formState.dirtyFields, name, true);
1528
1529
  output.dirtyFields = _formState.dirtyFields;
1529
1530
  shouldUpdateField =
1530
- shouldUpdateField || isPreviousDirty !== !isCurrentFieldPristine;
1531
+ shouldUpdateField ||
1532
+ (_proxyFormState.dirtyFields &&
1533
+ isPreviousDirty !== !isCurrentFieldPristine);
1531
1534
  }
1532
1535
  if (isBlurEvent) {
1533
1536
  const isPreviousFieldTouched = get(_formState.touchedFields, name);
@@ -1612,6 +1615,9 @@ function createFormControl(props = {}) {
1612
1615
  const isFieldArrayRoot = _names.array.has(_f.name);
1613
1616
  const fieldError = await validateField(field, get(_formValues, _f.name), shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation, isFieldArrayRoot);
1614
1617
  if (fieldError[_f.name]) {
1618
+ if (_f.name === context.name) {
1619
+ context.error = fieldError[context.name];
1620
+ }
1615
1621
  context.valid = false;
1616
1622
  if (shouldOnlyCheckValid) {
1617
1623
  break;
@@ -1628,7 +1634,7 @@ function createFormControl(props = {}) {
1628
1634
  (await executeBuiltInValidation(fieldValue, shouldOnlyCheckValid, context));
1629
1635
  }
1630
1636
  }
1631
- return context.valid;
1637
+ return context;
1632
1638
  };
1633
1639
  const _removeUnmounted = () => {
1634
1640
  for (const name of _names.unMount) {
@@ -1697,7 +1703,8 @@ function createFormControl(props = {}) {
1697
1703
  }
1698
1704
  (options.shouldDirty || options.shouldTouch) &&
1699
1705
  updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty, true);
1700
- options.shouldValidate && trigger(name);
1706
+ options.shouldValidate &&
1707
+ trigger(name);
1701
1708
  };
1702
1709
  const setValues = (name, value, options) => {
1703
1710
  for (const fieldKey in value) {
@@ -1795,8 +1802,17 @@ function createFormControl(props = {}) {
1795
1802
  isValid = isEmptyObject(errors);
1796
1803
  }
1797
1804
  else {
1798
- error = (await validateField(field, get(_formValues, name), shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation))[name];
1799
- _updateValid();
1805
+ if (_proxyFormState.isValid) {
1806
+ const buildInValidationResult = await executeBuiltInValidation(_fields, true, {
1807
+ name,
1808
+ valid: true,
1809
+ });
1810
+ error = buildInValidationResult.error || {};
1811
+ isValid = buildInValidationResult.valid;
1812
+ }
1813
+ if (!error || isEmptyObject(error)) {
1814
+ error = (await validateField(field, get(_formValues, name), shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation))[name];
1815
+ }
1800
1816
  }
1801
1817
  field._f.deps &&
1802
1818
  trigger(field._f.deps);
@@ -1820,12 +1836,13 @@ function createFormControl(props = {}) {
1820
1836
  else if (name) {
1821
1837
  validationResult = (await Promise.all(fieldNames.map(async (fieldName) => {
1822
1838
  const field = get(_fields, fieldName);
1823
- return await executeBuiltInValidation(field && field._f ? { [fieldName]: field } : field);
1839
+ return (await executeBuiltInValidation(field && field._f ? { [fieldName]: field } : field)).valid;
1824
1840
  }))).every(Boolean);
1825
1841
  !(!validationResult && !_formState.isValid) && _updateValid();
1826
1842
  }
1827
1843
  else {
1828
- validationResult = isValid = await executeBuiltInValidation(_fields);
1844
+ validationResult = isValid = (await executeBuiltInValidation(_fields))
1845
+ .valid;
1829
1846
  }
1830
1847
  _subjects.state.next({
1831
1848
  ...(!isString(name) ||
@@ -2074,7 +2091,7 @@ function createFormControl(props = {}) {
2074
2091
  _defaultValues = updatedValues;
2075
2092
  }
2076
2093
  if (!keepStateOptions.keepValues) {
2077
- if (keepStateOptions.keepDirtyValues) {
2094
+ if (keepStateOptions.keepDirtyValues || shouldCaptureDirtyFields) {
2078
2095
  for (const fieldName of _names.mount) {
2079
2096
  get(_formState.dirtyFields, fieldName)
2080
2097
  ? set(values, fieldName, get(_formValues, fieldName))
@@ -2164,6 +2181,11 @@ function createFormControl(props = {}) {
2164
2181
  }
2165
2182
  }
2166
2183
  };
2184
+ if (isFunction(_options.defaultValues)) {
2185
+ _options.defaultValues().then((values) => {
2186
+ reset(values, _options.resetOptions);
2187
+ });
2188
+ }
2167
2189
  return {
2168
2190
  control: {
2169
2191
  register,
@@ -2177,6 +2199,7 @@ function createFormControl(props = {}) {
2177
2199
  _removeUnmounted,
2178
2200
  _updateFieldArray,
2179
2201
  _getFieldArray,
2202
+ _reset,
2180
2203
  _subjects,
2181
2204
  _proxyFormState,
2182
2205
  get _fields() {
@@ -2274,7 +2297,9 @@ function useForm(props = {}) {
2274
2297
  dirtyFields: {},
2275
2298
  touchedFields: {},
2276
2299
  errors: {},
2277
- defaultValues: props.defaultValues,
2300
+ defaultValues: isFunction(props.defaultValues)
2301
+ ? undefined
2302
+ : props.defaultValues,
2278
2303
  });
2279
2304
  if (!_formControl.current) {
2280
2305
  _formControl.current = {
@@ -2286,7 +2311,7 @@ function useForm(props = {}) {
2286
2311
  control._options = props;
2287
2312
  useSubscribe({
2288
2313
  subject: control._subjects.state,
2289
- callback: React.useCallback((value) => {
2314
+ next: (value) => {
2290
2315
  if (shouldRenderFormState(value, control._proxyFormState, true)) {
2291
2316
  control._formState = {
2292
2317
  ...control._formState,
@@ -2294,7 +2319,7 @@ function useForm(props = {}) {
2294
2319
  };
2295
2320
  updateFormState({ ...control._formState });
2296
2321
  }
2297
- }, [control]),
2322
+ },
2298
2323
  });
2299
2324
  React.useEffect(() => {
2300
2325
  if (!control._stateFlags.mount) {
@@ -2307,6 +2332,11 @@ function useForm(props = {}) {
2307
2332
  }
2308
2333
  control._removeUnmounted();
2309
2334
  });
2335
+ React.useEffect(() => {
2336
+ if (props.values && !deepEqual(props.values, control._defaultValues)) {
2337
+ control._reset(props.values, control._options.resetOptions);
2338
+ }
2339
+ }, [props.values, control]);
2310
2340
  React.useEffect(() => {
2311
2341
  formState.submitCount && control._focusError();
2312
2342
  }, [control, formState.submitCount]);