react-hook-form 7.23.0-next.1 → 7.24.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.
@@ -142,8 +142,10 @@ function useFormState(props) {
142
142
  errors: false,
143
143
  });
144
144
  const _name = React.useRef(name);
145
+ const _mounted = React.useRef(true);
145
146
  _name.current = name;
146
- const callback = React.useCallback((value) => shouldSubscribeByName(_name.current, value.name, exact) &&
147
+ const callback = React.useCallback((value) => _mounted.current &&
148
+ shouldSubscribeByName(_name.current, value.name, exact) &&
147
149
  shouldRenderFormState(value, _localProxyFormState.current) &&
148
150
  updateFormState(Object.assign(Object.assign({}, control._formState), value)), [control, exact]);
149
151
  useSubscribe({
@@ -151,6 +153,9 @@ function useFormState(props) {
151
153
  callback,
152
154
  subject: control._subjects.state,
153
155
  });
156
+ React.useEffect(() => () => {
157
+ _mounted.current = false;
158
+ }, []);
154
159
  return getProxyFormState(formState, control._proxyFormState, _localProxyFormState.current, false);
155
160
  }
156
161
 
@@ -226,9 +231,7 @@ function useController(props) {
226
231
  control,
227
232
  name,
228
233
  });
229
- const _name = React.useRef(name);
230
- _name.current = name;
231
- const registerProps = control.register(name, Object.assign(Object.assign({}, props.rules), { value }));
234
+ const _registerProps = React.useRef(control.register(name, Object.assign(Object.assign({}, props.rules), { value })));
232
235
  React.useEffect(() => {
233
236
  const updateMounted = (name, value) => {
234
237
  const field = get(control._fields, name);
@@ -239,36 +242,36 @@ function useController(props) {
239
242
  updateMounted(name, true);
240
243
  return () => {
241
244
  const _shouldUnregisterField = control._options.shouldUnregister || shouldUnregister;
242
- isArrayField
245
+ (isArrayField
243
246
  ? _shouldUnregisterField && !control._stateFlags.action
244
- : _shouldUnregisterField
245
- ? control.unregister(name)
246
- : updateMounted(name, false);
247
+ : _shouldUnregisterField)
248
+ ? control.unregister(name)
249
+ : updateMounted(name, false);
247
250
  };
248
251
  }, [name, control, isArrayField, shouldUnregister]);
249
252
  return {
250
253
  field: {
251
- onChange: (event) => {
252
- registerProps.onChange({
254
+ name,
255
+ value,
256
+ onChange: React.useCallback((event) => {
257
+ _registerProps.current.onChange({
253
258
  target: {
254
259
  value: getEventValue(event),
255
260
  name: name,
256
261
  },
257
262
  type: EVENTS.CHANGE,
258
263
  });
259
- },
260
- onBlur: () => {
261
- registerProps.onBlur({
264
+ }, [name]),
265
+ onBlur: React.useCallback(() => {
266
+ _registerProps.current.onBlur({
262
267
  target: {
263
268
  value: get(control._formValues, name),
264
269
  name: name,
265
270
  },
266
271
  type: EVENTS.BLUR,
267
272
  });
268
- },
269
- name,
270
- value,
271
- ref: (elm) => {
273
+ }, [name, control]),
274
+ ref: React.useCallback((elm) => {
272
275
  const field = get(control._fields, name);
273
276
  if (elm && field && elm.focus) {
274
277
  field._f.ref = {
@@ -277,7 +280,7 @@ function useController(props) {
277
280
  reportValidity: () => elm.reportValidity(),
278
281
  };
279
282
  }
280
- },
283
+ }, [name, control]),
281
284
  },
282
285
  formState,
283
286
  fieldState: {
@@ -402,14 +405,14 @@ function insert(data, index, value) {
402
405
  }
403
406
 
404
407
  var moveArrayAt = (data, from, to) => {
405
- if (Array.isArray(data)) {
406
- if (isUndefined(data[to])) {
407
- data[to] = undefined;
408
- }
409
- data.splice(to, 0, data.splice(from, 1)[0]);
410
- return data;
408
+ if (!Array.isArray(data)) {
409
+ return [];
410
+ }
411
+ if (isUndefined(data[to])) {
412
+ data[to] = undefined;
411
413
  }
412
- return [];
414
+ data.splice(to, 0, data.splice(from, 1)[0]);
415
+ return data;
413
416
  };
414
417
 
415
418
  function prepend(data, value) {
@@ -537,14 +540,14 @@ const useFieldArray = (props) => {
537
540
  control._updateFieldArray(name, updateAt, {
538
541
  argA: index,
539
542
  argB: value,
540
- }, updatedFieldArrayValues, true, false, false);
543
+ }, updatedFieldArrayValues, true, false);
541
544
  };
542
545
  const replace = (value) => {
543
546
  const updatedFieldArrayValues = convertToArrayPayload(value);
544
547
  ids.current = updatedFieldArrayValues.map(generateId);
545
548
  updateValues([...updatedFieldArrayValues]);
546
549
  setFields([...updatedFieldArrayValues]);
547
- control._updateFieldArray(name, () => updatedFieldArrayValues, {}, [...updatedFieldArrayValues], true, false, false);
550
+ control._updateFieldArray(name, () => updatedFieldArrayValues, {}, [...updatedFieldArrayValues], true, false);
548
551
  };
549
552
  React.useEffect(() => {
550
553
  control._stateFlags.action = false;
@@ -1140,24 +1143,25 @@ function createFormControl(props = {}) {
1140
1143
  }
1141
1144
  return isValid;
1142
1145
  };
1143
- const _updateFieldArray = (name, method, args, values = [], shouldSetValues = true, shouldSetFields = true, shouldSetError = true) => {
1146
+ const _updateFieldArray = (name, method, args, values = [], shouldSetValues = true, shouldSetFields = true) => {
1144
1147
  _stateFlags.action = true;
1145
- if (shouldSetFields && get(_fields, name)) {
1148
+ if (shouldSetFields && Array.isArray(get(_fields, name))) {
1146
1149
  const fieldValues = method(get(_fields, name), args.argA, args.argB);
1147
1150
  shouldSetValues && set(_fields, name, fieldValues);
1148
1151
  }
1149
- if (shouldSetError && Array.isArray(get(_formState.errors, name))) {
1152
+ if (_proxyFormState.errors &&
1153
+ shouldSetFields &&
1154
+ Array.isArray(get(_formState.errors, name))) {
1150
1155
  const errors = method(get(_formState.errors, name), args.argA, args.argB);
1151
1156
  shouldSetValues && set(_formState.errors, name, errors);
1152
1157
  unsetEmptyArray(_formState.errors, name);
1153
1158
  }
1154
- if (_proxyFormState.touchedFields && get(_formState.touchedFields, name)) {
1159
+ if (_proxyFormState.touchedFields &&
1160
+ Array.isArray(get(_formState.touchedFields, name))) {
1155
1161
  const touchedFields = method(get(_formState.touchedFields, name), args.argA, args.argB);
1156
- shouldSetValues &&
1157
- set(_formState.touchedFields, name, touchedFields);
1158
- unsetEmptyArray(_formState.touchedFields, name);
1162
+ shouldSetValues && set(_formState.touchedFields, name, touchedFields);
1159
1163
  }
1160
- if (_proxyFormState.dirtyFields || _proxyFormState.isDirty) {
1164
+ if (_proxyFormState.dirtyFields) {
1161
1165
  _formState.dirtyFields = getDirtyFields(_defaultValues, _formValues);
1162
1166
  }
1163
1167
  _subjects.state.next({
@@ -1183,7 +1187,7 @@ function createFormControl(props = {}) {
1183
1187
  _stateFlags.mount && _updateValid();
1184
1188
  }
1185
1189
  };
1186
- const updateTouchAndDirty = (name, fieldValue, isCurrentTouched, shouldRender = true) => {
1190
+ const updateTouchAndDirty = (name, fieldValue, isBlurEvent, shouldDirty, shouldRender) => {
1187
1191
  let isFieldDirty = false;
1188
1192
  const output = {
1189
1193
  name,
@@ -1194,7 +1198,7 @@ function createFormControl(props = {}) {
1194
1198
  _formState.isDirty = output.isDirty = _getDirty();
1195
1199
  isFieldDirty = isPreviousFormDirty !== output.isDirty;
1196
1200
  }
1197
- if (_proxyFormState.dirtyFields && !isCurrentTouched) {
1201
+ if (_proxyFormState.dirtyFields && (!isBlurEvent || shouldDirty)) {
1198
1202
  const isPreviousFieldDirty = get(_formState.dirtyFields, name);
1199
1203
  const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
1200
1204
  isCurrentFieldPristine
@@ -1205,13 +1209,13 @@ function createFormControl(props = {}) {
1205
1209
  isFieldDirty ||
1206
1210
  isPreviousFieldDirty !== get(_formState.dirtyFields, name);
1207
1211
  }
1208
- if (isCurrentTouched && !isPreviousFieldTouched) {
1209
- set(_formState.touchedFields, name, isCurrentTouched);
1212
+ if (isBlurEvent && !isPreviousFieldTouched) {
1213
+ set(_formState.touchedFields, name, isBlurEvent);
1210
1214
  output.touchedFields = _formState.touchedFields;
1211
1215
  isFieldDirty =
1212
1216
  isFieldDirty ||
1213
1217
  (_proxyFormState.touchedFields &&
1214
- isPreviousFieldTouched !== isCurrentTouched);
1218
+ isPreviousFieldTouched !== isBlurEvent);
1215
1219
  }
1216
1220
  isFieldDirty && shouldRender && _subjects.state.next(output);
1217
1221
  return isFieldDirty ? output : {};
@@ -1355,7 +1359,7 @@ function createFormControl(props = {}) {
1355
1359
  }
1356
1360
  }
1357
1361
  (options.shouldDirty || options.shouldTouch) &&
1358
- updateTouchAndDirty(name, fieldValue, options.shouldTouch);
1362
+ updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty, true);
1359
1363
  options.shouldValidate && trigger(name);
1360
1364
  };
1361
1365
  const setValues = (name, value, options) => {
@@ -1374,7 +1378,8 @@ function createFormControl(props = {}) {
1374
1378
  const setValue = (name, value, options = {}) => {
1375
1379
  const field = get(_fields, name);
1376
1380
  const isFieldArray = _names.array.has(name);
1377
- set(_formValues, name, value);
1381
+ const cloneValue = cloneObject(value);
1382
+ set(_formValues, name, cloneValue);
1378
1383
  if (isFieldArray) {
1379
1384
  _subjects.array.next({
1380
1385
  name,
@@ -1386,14 +1391,14 @@ function createFormControl(props = {}) {
1386
1391
  _subjects.state.next({
1387
1392
  name,
1388
1393
  dirtyFields: _formState.dirtyFields,
1389
- isDirty: _getDirty(name, value),
1394
+ isDirty: _getDirty(name, cloneValue),
1390
1395
  });
1391
1396
  }
1392
1397
  }
1393
1398
  else {
1394
- field && !field._f && !isNullOrUndefined(value)
1395
- ? setValues(name, value, options)
1396
- : setFieldValue(name, value, options);
1399
+ field && !field._f && !isNullOrUndefined(cloneValue)
1400
+ ? setValues(name, cloneValue, options)
1401
+ : setFieldValue(name, cloneValue, options);
1397
1402
  }
1398
1403
  isWatched(name, _names) && _subjects.state.next({});
1399
1404
  _subjects.watch.next({
@@ -1417,13 +1422,13 @@ function createFormControl(props = {}) {
1417
1422
  !field._f.deps) ||
1418
1423
  skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, validationModeAfterSubmit, validationModeBeforeSubmit);
1419
1424
  const watched = isWatched(name, _names, isBlurEvent);
1425
+ set(_formValues, name, fieldValue);
1420
1426
  if (isBlurEvent) {
1421
1427
  field._f.onBlur && field._f.onBlur(event);
1422
1428
  }
1423
1429
  else if (field._f.onChange) {
1424
1430
  field._f.onChange(event);
1425
1431
  }
1426
- set(_formValues, name, fieldValue);
1427
1432
  const fieldState = updateTouchAndDirty(name, fieldValue, isBlurEvent, false);
1428
1433
  const shouldRender = !isEmptyObject(fieldState) || watched;
1429
1434
  !isBlurEvent &&
@@ -1498,13 +1503,18 @@ function createFormControl(props = {}) {
1498
1503
  ? get(values, fieldNames)
1499
1504
  : fieldNames.map((name) => get(values, name));
1500
1505
  };
1506
+ const _getFieldState = (name, formState) => ({
1507
+ invalid: !!get((formState || _formState).errors, name),
1508
+ isDirty: !!get((formState || _formState).dirtyFields, name),
1509
+ isTouched: !!get((formState || _formState).touchedFields, name),
1510
+ error: get((formState || _formState).errors, name),
1511
+ });
1501
1512
  const clearErrors = (name) => {
1502
1513
  name
1503
1514
  ? convertToArrayPayload(name).forEach((inputName) => unset(_formState.errors, inputName))
1504
1515
  : (_formState.errors = {});
1505
1516
  _subjects.state.next({
1506
1517
  errors: _formState.errors,
1507
- isValid: true,
1508
1518
  });
1509
1519
  };
1510
1520
  const setError = (name, error, options) => {
@@ -1654,27 +1664,29 @@ function createFormControl(props = {}) {
1654
1664
  }
1655
1665
  };
1656
1666
  const resetField = (name, options = {}) => {
1657
- if (isUndefined(options.defaultValue)) {
1658
- setValue(name, get(_defaultValues, name));
1659
- }
1660
- else {
1661
- setValue(name, options.defaultValue);
1662
- set(_defaultValues, name, options.defaultValue);
1663
- }
1664
- if (!options.keepTouched) {
1665
- unset(_formState.touchedFields, name);
1666
- }
1667
- if (!options.keepDirty) {
1668
- unset(_formState.dirtyFields, name);
1669
- _formState.isDirty = options.defaultValue
1670
- ? _getDirty(name, get(_defaultValues, name))
1671
- : _getDirty();
1672
- }
1673
- if (!options.keepError) {
1674
- unset(_formState.errors, name);
1675
- _proxyFormState.isValid && _updateValid();
1667
+ if (get(_fields, name)) {
1668
+ if (isUndefined(options.defaultValue)) {
1669
+ setValue(name, get(_defaultValues, name));
1670
+ }
1671
+ else {
1672
+ setValue(name, options.defaultValue);
1673
+ set(_defaultValues, name, options.defaultValue);
1674
+ }
1675
+ if (!options.keepTouched) {
1676
+ unset(_formState.touchedFields, name);
1677
+ }
1678
+ if (!options.keepDirty) {
1679
+ unset(_formState.dirtyFields, name);
1680
+ _formState.isDirty = options.defaultValue
1681
+ ? _getDirty(name, get(_defaultValues, name))
1682
+ : _getDirty();
1683
+ }
1684
+ if (!options.keepError) {
1685
+ unset(_formState.errors, name);
1686
+ _proxyFormState.isValid && _updateValid();
1687
+ }
1688
+ _subjects.state.next(Object.assign({}, _formState));
1676
1689
  }
1677
- _subjects.state.next(Object.assign({}, _formState));
1678
1690
  };
1679
1691
  const reset = (formValues, keepStateOptions = {}) => {
1680
1692
  const updatedValues = formValues || _defaultValues;
@@ -1825,6 +1837,7 @@ function createFormControl(props = {}) {
1825
1837
  unregister,
1826
1838
  setError,
1827
1839
  setFocus,
1840
+ _getFieldState,
1828
1841
  };
1829
1842
  }
1830
1843