react-hook-form 7.17.1 → 7.17.5
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/CHANGELOG.md +1185 -0
- package/README.md +18 -0
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +76 -54
- package/dist/index.esm.js.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/dist/logic/shouldSubscribeByName.d.ts +2 -0
- package/dist/types/controller.d.ts +6 -8
- package/dist/types/fieldArray.d.ts +1 -1
- package/dist/types/fields.d.ts +2 -2
- package/dist/types/form.d.ts +6 -6
- package/dist/types/utils.d.ts +23 -10
- package/dist/useSubscribe.d.ts +4 -3
- package/dist/useWatch.d.ts +4 -4
- package/dist/utils/cloneObject.d.ts +1 -1
- package/dist/utils/convertToArrayPayload.d.ts +1 -1
- package/dist/utils/get.d.ts +1 -1
- package/dist/utils/{Subject.d.ts → subject.d.ts} +3 -2
- package/package.json +17 -19
package/dist/index.esm.js
CHANGED
@@ -101,29 +101,41 @@ var shouldRenderFormState = (formStateData, _proxyFormState, isRoot) => {
|
|
101
101
|
(!isRoot || VALIDATION_MODE.all)));
|
102
102
|
};
|
103
103
|
|
104
|
-
var convertToArrayPayload = (value) => Array.isArray(value) ? value : [value];
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
104
|
+
var convertToArrayPayload = (value) => (Array.isArray(value) ? value : [value]);
|
105
|
+
|
106
|
+
var shouldSubscribeByName = (name, signalName) => !name ||
|
107
|
+
!signalName ||
|
108
|
+
convertToArrayPayload(name).some((currentName) => currentName &&
|
109
|
+
(currentName.startsWith(signalName) ||
|
110
|
+
signalName.startsWith(currentName)));
|
111
|
+
|
112
|
+
const tearDown = (_unsubscribe) => {
|
113
|
+
if (_unsubscribe.current) {
|
114
|
+
_unsubscribe.current.unsubscribe();
|
115
|
+
_unsubscribe.current = undefined;
|
114
116
|
}
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
}
|
117
|
+
};
|
118
|
+
const updateSubscriptionProps = ({ _unsubscribe, props }) => () => {
|
119
|
+
if (props.disabled) {
|
120
|
+
tearDown(_unsubscribe);
|
121
|
+
}
|
122
|
+
else if (!_unsubscribe.current) {
|
123
|
+
_unsubscribe.current = props.subject.subscribe({
|
124
|
+
next: props.callback,
|
125
|
+
});
|
124
126
|
}
|
125
|
-
|
126
|
-
|
127
|
+
};
|
128
|
+
function useSubscribe(props) {
|
129
|
+
const _unsubscribe = React.useRef();
|
130
|
+
const _updateSubscription = React.useRef(() => { });
|
131
|
+
_updateSubscription.current = updateSubscriptionProps({
|
132
|
+
_unsubscribe,
|
133
|
+
props,
|
134
|
+
});
|
135
|
+
!props.skipEarlySubscription && _updateSubscription.current();
|
136
|
+
React.useEffect(() => {
|
137
|
+
_updateSubscription.current();
|
138
|
+
return () => tearDown(_unsubscribe);
|
127
139
|
}, []);
|
128
140
|
}
|
129
141
|
|
@@ -143,12 +155,11 @@ function useFormState(props) {
|
|
143
155
|
_name.current = name;
|
144
156
|
useSubscribe({
|
145
157
|
disabled,
|
146
|
-
callback: (formState) => (
|
147
|
-
!formState.name ||
|
148
|
-
convertToArrayPayload(_name.current).includes(formState.name)) &&
|
158
|
+
callback: (formState) => shouldSubscribeByName(_name.current, formState.name) &&
|
149
159
|
shouldRenderFormState(formState, _localProxyFormState.current) &&
|
150
160
|
updateFormState(Object.assign(Object.assign({}, control._formState), formState)),
|
151
161
|
subject: control._subjects.state,
|
162
|
+
skipEarlySubscription: true,
|
152
163
|
});
|
153
164
|
return getProxyFormState(formState, control._proxyFormState, _localProxyFormState.current, false);
|
154
165
|
}
|
@@ -166,7 +177,7 @@ function useController(props) {
|
|
166
177
|
useSubscribe({
|
167
178
|
subject: control._subjects.control,
|
168
179
|
callback: (data) => (!data.name || _name.current === data.name) &&
|
169
|
-
setInputStateValue(get(data.values,
|
180
|
+
setInputStateValue(get(data.values, _name.current)),
|
170
181
|
});
|
171
182
|
const registerProps = control.register(name, Object.assign(Object.assign({}, props.rules), { value }));
|
172
183
|
const updateMounted = React.useCallback((name, value) => {
|
@@ -366,15 +377,18 @@ const useFieldArray = (props) => {
|
|
366
377
|
const { control = methods.control, name, keyName = 'id', shouldUnregister, } = props;
|
367
378
|
const [fields, setFields] = React.useState(mapIds(control._getFieldArray(name), keyName));
|
368
379
|
const _fieldIds = React.useRef(fields);
|
380
|
+
const _name = React.useRef(name);
|
381
|
+
_name.current = name;
|
369
382
|
_fieldIds.current = fields;
|
370
383
|
control._names.array.add(name);
|
371
384
|
useSubscribe({
|
372
385
|
callback: ({ values, name: fieldArrayName }) => {
|
373
|
-
if (fieldArrayName ===
|
374
|
-
setFields(mapIds(get(values,
|
386
|
+
if (fieldArrayName === _name.current || !fieldArrayName) {
|
387
|
+
setFields(mapIds(get(values, _name.current), keyName));
|
375
388
|
}
|
376
389
|
},
|
377
390
|
subject: control._subjects.array,
|
391
|
+
skipEarlySubscription: true,
|
378
392
|
});
|
379
393
|
const updateValues = React.useCallback((updatedFieldArrayValuesWithKey) => {
|
380
394
|
const updatedFieldArrayValues = omitKeys(updatedFieldArrayValuesWithKey, keyName);
|
@@ -483,6 +497,8 @@ const useFieldArray = (props) => {
|
|
483
497
|
};
|
484
498
|
};
|
485
499
|
|
500
|
+
var isFunction = (value) => typeof value === 'function';
|
501
|
+
|
486
502
|
function cloneObject(data) {
|
487
503
|
let copy;
|
488
504
|
const isArray = Array.isArray(data);
|
@@ -495,6 +511,10 @@ function cloneObject(data) {
|
|
495
511
|
else if (isArray || isObject(data)) {
|
496
512
|
copy = isArray ? [] : {};
|
497
513
|
for (const key in data) {
|
514
|
+
if (isFunction(data[key])) {
|
515
|
+
copy = data;
|
516
|
+
break;
|
517
|
+
}
|
498
518
|
copy[key] = cloneObject(data[key]);
|
499
519
|
}
|
500
520
|
}
|
@@ -547,8 +567,6 @@ var getValidationModes = (mode) => ({
|
|
547
567
|
|
548
568
|
var isBoolean = (value) => typeof value === 'boolean';
|
549
569
|
|
550
|
-
var isFunction = (value) => typeof value === 'function';
|
551
|
-
|
552
570
|
var isHTMLElement = (value) => value instanceof HTMLElement;
|
553
571
|
|
554
572
|
var isMultipleSelect = (element) => element.type === `select-multiple`;
|
@@ -563,7 +581,7 @@ var isWeb = typeof window !== 'undefined' &&
|
|
563
581
|
typeof window.HTMLElement !== 'undefined' &&
|
564
582
|
typeof document !== 'undefined';
|
565
583
|
|
566
|
-
var live = (ref) =>
|
584
|
+
var live = (ref) => isHTMLElement(ref) && document.contains(ref);
|
567
585
|
|
568
586
|
class Subscription {
|
569
587
|
constructor() {
|
@@ -1203,7 +1221,9 @@ function createFormControl(props = {}) {
|
|
1203
1221
|
for (const name of _names.unMount) {
|
1204
1222
|
const field = get(_fields, name);
|
1205
1223
|
field &&
|
1206
|
-
(field._f.refs
|
1224
|
+
(field._f.refs
|
1225
|
+
? field._f.refs.every((ref) => !live(ref))
|
1226
|
+
: !live(field._f.ref)) &&
|
1207
1227
|
unregister(name);
|
1208
1228
|
}
|
1209
1229
|
_names.unMount = new Set();
|
@@ -1226,7 +1246,7 @@ function createFormControl(props = {}) {
|
|
1226
1246
|
isGlobal && (_names.watchAll = true);
|
1227
1247
|
return fieldValues;
|
1228
1248
|
};
|
1229
|
-
const _getFieldArray = (name) => get(_stateFlags.mount ? _formValues : _defaultValues, name, []);
|
1249
|
+
const _getFieldArray = (name) => get(_stateFlags.mount ? _formValues : _defaultValues, name, props.shouldUnregister ? get(_defaultValues, name, []) : []);
|
1230
1250
|
const setFieldValue = (name, value, options = {}, shouldRender) => {
|
1231
1251
|
const field = get(_fields, name);
|
1232
1252
|
let fieldValue = value;
|
@@ -1324,8 +1344,8 @@ function createFormControl(props = {}) {
|
|
1324
1344
|
!field._f.deps) ||
|
1325
1345
|
skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, validationModeAfterSubmit, validationModeBeforeSubmit);
|
1326
1346
|
const isWatched = isFieldWatched(name, isBlurEvent);
|
1327
|
-
if (isBlurEvent
|
1328
|
-
field._f.onBlur(event);
|
1347
|
+
if (isBlurEvent) {
|
1348
|
+
field._f.onBlur && field._f.onBlur(event);
|
1329
1349
|
}
|
1330
1350
|
else if (field._f.onChange) {
|
1331
1351
|
field._f.onChange(event);
|
@@ -1415,6 +1435,7 @@ function createFormControl(props = {}) {
|
|
1415
1435
|
: (_formState.errors = {});
|
1416
1436
|
_subjects.state.next({
|
1417
1437
|
errors: _formState.errors,
|
1438
|
+
isValid: true,
|
1418
1439
|
});
|
1419
1440
|
};
|
1420
1441
|
const setError = (name, error, options) => {
|
@@ -1489,7 +1510,7 @@ function createFormControl(props = {}) {
|
|
1489
1510
|
field = {
|
1490
1511
|
_f: isRadioOrCheckbox
|
1491
1512
|
? Object.assign(Object.assign({}, field._f), { refs: [
|
1492
|
-
...compact(field._f.refs || []).filter(
|
1513
|
+
...compact(field._f.refs || []).filter(live),
|
1493
1514
|
fieldRef,
|
1494
1515
|
], ref: { type: fieldRef.type, name } }) : Object.assign(Object.assign({}, field._f), { ref: fieldRef }),
|
1495
1516
|
};
|
@@ -1558,10 +1579,13 @@ function createFormControl(props = {}) {
|
|
1558
1579
|
}
|
1559
1580
|
};
|
1560
1581
|
const reset = (formValues, keepStateOptions = {}) => {
|
1582
|
+
const hasUpdatedFormValues = !isEmptyObject(formValues);
|
1561
1583
|
const updatedValues = formValues || _defaultValues;
|
1562
1584
|
const cloneUpdatedValues = cloneObject(updatedValues);
|
1585
|
+
if (!keepStateOptions.keepDefaultValues) {
|
1586
|
+
_defaultValues = updatedValues;
|
1587
|
+
}
|
1563
1588
|
if (!keepStateOptions.keepValues) {
|
1564
|
-
_formValues = props.shouldUnregister ? {} : cloneUpdatedValues;
|
1565
1589
|
if (isWeb) {
|
1566
1590
|
for (const name of _names.mount) {
|
1567
1591
|
const field = get(_fields, name);
|
@@ -1578,16 +1602,14 @@ function createFormControl(props = {}) {
|
|
1578
1602
|
}
|
1579
1603
|
}
|
1580
1604
|
}
|
1581
|
-
|
1582
|
-
|
1583
|
-
|
1584
|
-
|
1585
|
-
|
1605
|
+
_formValues = props.shouldUnregister
|
1606
|
+
? keepStateOptions.keepDefaultValues
|
1607
|
+
? _defaultValues
|
1608
|
+
: {}
|
1609
|
+
: cloneUpdatedValues;
|
1586
1610
|
_fields = {};
|
1587
1611
|
_subjects.control.next({
|
1588
|
-
values:
|
1589
|
-
? _defaultValues
|
1590
|
-
: Object.assign({}, updatedValues),
|
1612
|
+
values: hasUpdatedFormValues ? cloneUpdatedValues : _defaultValues,
|
1591
1613
|
});
|
1592
1614
|
_subjects.watch.next({});
|
1593
1615
|
_subjects.array.next({
|
@@ -1609,14 +1631,16 @@ function createFormControl(props = {}) {
|
|
1609
1631
|
isDirty: keepStateOptions.keepDirty
|
1610
1632
|
? _formState.isDirty
|
1611
1633
|
: keepStateOptions.keepDefaultValues
|
1612
|
-
? deepEqual(formValues, _defaultValues)
|
1634
|
+
? !deepEqual(formValues, _defaultValues)
|
1613
1635
|
: false,
|
1614
1636
|
isSubmitted: keepStateOptions.keepIsSubmitted
|
1615
1637
|
? _formState.isSubmitted
|
1616
1638
|
: false,
|
1617
1639
|
dirtyFields: keepStateOptions.keepDirty
|
1618
1640
|
? _formState.dirtyFields
|
1619
|
-
:
|
1641
|
+
: (keepStateOptions.keepDefaultValues && formValues
|
1642
|
+
? Object.entries(formValues).reduce((previous, [key, value]) => (Object.assign(Object.assign({}, previous), { [key]: value !== get(_defaultValues, key) })), {})
|
1643
|
+
: {}),
|
1620
1644
|
touchedFields: keepStateOptions.keepTouched
|
1621
1645
|
? _formState.touchedFields
|
1622
1646
|
: {},
|
@@ -1630,7 +1654,10 @@ function createFormControl(props = {}) {
|
|
1630
1654
|
!_proxyFormState.isValid || !!keepStateOptions.keepIsValid;
|
1631
1655
|
_stateFlags.watch = !!props.shouldUnregister;
|
1632
1656
|
};
|
1633
|
-
const setFocus = (name) =>
|
1657
|
+
const setFocus = (name) => {
|
1658
|
+
const field = get(_fields, name)._f;
|
1659
|
+
(field.ref.focus ? field.ref : field.refs[0]).focus();
|
1660
|
+
};
|
1634
1661
|
return {
|
1635
1662
|
control: {
|
1636
1663
|
register,
|
@@ -1753,13 +1780,8 @@ function useWatch(props) {
|
|
1753
1780
|
useSubscribe({
|
1754
1781
|
disabled,
|
1755
1782
|
subject: control._subjects.watch,
|
1756
|
-
callback: (
|
1757
|
-
if (
|
1758
|
-
!name ||
|
1759
|
-
convertToArrayPayload(_name.current).some((currentName) => name &&
|
1760
|
-
currentName &&
|
1761
|
-
(name.startsWith(currentName) ||
|
1762
|
-
currentName.startsWith(name)))) {
|
1783
|
+
callback: (formState) => {
|
1784
|
+
if (shouldSubscribeByName(_name.current, formState.name)) {
|
1763
1785
|
control._stateFlags.mount = true;
|
1764
1786
|
const fieldValues = control._getWatch(_name.current, defaultValue);
|
1765
1787
|
updateValue(isObject(fieldValues)
|