react-hook-form 7.19.4 → 7.20.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.
- package/CHANGELOG.md +42 -0
- package/README.md +3 -0
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +70 -74
- 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/generateWatchOutput.d.ts +2 -1
- package/dist/logic/isWatched.d.ts +3 -0
- package/dist/logic/shouldSubscribeByName.d.ts +1 -1
- package/dist/types/form.d.ts +3 -1
- package/dist/useWatch.d.ts +4 -1
- package/dist/utils/objectHasFunction.d.ts +2 -0
- package/package.json +17 -15
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) =>
|
107
|
-
|
108
|
-
name
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
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
|
131
|
-
|
132
|
-
_subscription,
|
133
|
-
props,
|
134
|
-
});
|
116
|
+
const _props = React.useRef(props);
|
117
|
+
_props.current = props;
|
135
118
|
React.useEffect(() => {
|
136
|
-
|
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: (
|
157
|
-
shouldRenderFormState(
|
158
|
-
updateFormState(Object.assign(Object.assign({}, control._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);
|
@@ -163,7 +155,7 @@ function useFormState(props) {
|
|
163
155
|
|
164
156
|
var isString = (value) => typeof value === 'string';
|
165
157
|
|
166
|
-
|
158
|
+
var generateWatchOutput = (names, _names, formValues, isGlobal) => {
|
167
159
|
const isArray = Array.isArray(names);
|
168
160
|
if (isString(names)) {
|
169
161
|
isGlobal && _names.watch.add(names);
|
@@ -175,20 +167,32 @@ function generateWatchOutput(names, _names, formValues, isGlobal) {
|
|
175
167
|
}
|
176
168
|
isGlobal && (_names.watchAll = true);
|
177
169
|
return formValues;
|
178
|
-
}
|
170
|
+
};
|
171
|
+
|
172
|
+
var isFunction = (value) => typeof value === 'function';
|
173
|
+
|
174
|
+
var objectHasFunction = (data) => {
|
175
|
+
for (const key in data) {
|
176
|
+
if (isFunction(data[key])) {
|
177
|
+
return true;
|
178
|
+
}
|
179
|
+
}
|
180
|
+
return false;
|
181
|
+
};
|
179
182
|
|
180
183
|
function useWatch(props) {
|
181
184
|
const methods = useFormContext();
|
182
|
-
const { control = methods.control, name, defaultValue, disabled, } = props || {};
|
185
|
+
const { control = methods.control, name, defaultValue, disabled, exact, } = props || {};
|
183
186
|
const _name = React.useRef(name);
|
184
187
|
_name.current = name;
|
185
188
|
useSubscribe({
|
186
189
|
disabled,
|
187
190
|
subject: control._subjects.watch,
|
188
191
|
callback: (formState) => {
|
189
|
-
if (shouldSubscribeByName(_name.current, formState.name)) {
|
192
|
+
if (shouldSubscribeByName(_name.current, formState.name, exact)) {
|
190
193
|
const fieldValues = generateWatchOutput(_name.current, control._names, formState.values || control._formValues);
|
191
|
-
updateValue(isUndefined(_name.current)
|
194
|
+
updateValue(isUndefined(_name.current) ||
|
195
|
+
(isObject(fieldValues) && !objectHasFunction(fieldValues))
|
192
196
|
? Object.assign({}, fieldValues) : Array.isArray(fieldValues)
|
193
197
|
? [...fieldValues]
|
194
198
|
: fieldValues);
|
@@ -207,10 +211,12 @@ function useWatch(props) {
|
|
207
211
|
function useController(props) {
|
208
212
|
const methods = useFormContext();
|
209
213
|
const { name, control = methods.control, shouldUnregister } = props;
|
214
|
+
const isArrayField = isNameInFieldArray(control._names.array, name);
|
210
215
|
const value = useWatch({
|
211
216
|
control,
|
212
217
|
name,
|
213
218
|
defaultValue: get(control._formValues, name, get(control._defaultValues, name, props.defaultValue)),
|
219
|
+
exact: !isArrayField,
|
214
220
|
});
|
215
221
|
const formState = useFormState({
|
216
222
|
control,
|
@@ -229,7 +235,7 @@ function useController(props) {
|
|
229
235
|
updateMounted(name, true);
|
230
236
|
return () => {
|
231
237
|
const _shouldUnregisterField = control._options.shouldUnregister || shouldUnregister;
|
232
|
-
if (
|
238
|
+
if (isArrayField
|
233
239
|
? _shouldUnregisterField && !control._stateFlags.action
|
234
240
|
: _shouldUnregisterField) {
|
235
241
|
control.unregister(name, { keepDefaultValue: true });
|
@@ -238,7 +244,7 @@ function useController(props) {
|
|
238
244
|
updateMounted(name, false);
|
239
245
|
}
|
240
246
|
};
|
241
|
-
}, [name, control, shouldUnregister]);
|
247
|
+
}, [name, control, isArrayField, shouldUnregister]);
|
242
248
|
return {
|
243
249
|
field: {
|
244
250
|
onChange: (event) => {
|
@@ -253,7 +259,7 @@ function useController(props) {
|
|
253
259
|
onBlur: () => {
|
254
260
|
registerProps.onBlur({
|
255
261
|
target: {
|
256
|
-
value,
|
262
|
+
value: get(control._formValues, name),
|
257
263
|
name: name,
|
258
264
|
},
|
259
265
|
type: EVENTS.BLUR,
|
@@ -341,6 +347,12 @@ var getFocusFieldName = (name, index, options = {}) => options.shouldFocus || is
|
|
341
347
|
`${name}.${isUndefined(options.focusIndex) ? index : options.focusIndex}.`
|
342
348
|
: '';
|
343
349
|
|
350
|
+
var isWatched = (name, _names, isBlurEvent) => !isBlurEvent &&
|
351
|
+
(_names.watchAll ||
|
352
|
+
_names.watch.has(name) ||
|
353
|
+
[..._names.watch].some((watchName) => name.startsWith(watchName) &&
|
354
|
+
/^\.\w+/.test(name.slice(watchName.length))));
|
355
|
+
|
344
356
|
var mapCurrentIds = (values, _fieldIds, keyName) => values.map((value, index) => {
|
345
357
|
const output = _fieldIds.current[index];
|
346
358
|
return Object.assign(Object.assign({}, value), (output ? { [keyName]: output[keyName] } : {}));
|
@@ -436,44 +448,44 @@ const useFieldArray = (props) => {
|
|
436
448
|
const append$1 = (value, options) => {
|
437
449
|
const appendValue = convertToArrayPayload(value);
|
438
450
|
const updatedFieldArrayValuesWithKey = append(mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName), mapIds(appendValue, keyName));
|
451
|
+
setFields(updatedFieldArrayValuesWithKey);
|
439
452
|
control._updateFieldArray(name, append, {
|
440
453
|
argA: fillEmptyArray(value),
|
441
454
|
}, updateValues(updatedFieldArrayValuesWithKey));
|
442
|
-
setFields(updatedFieldArrayValuesWithKey);
|
443
455
|
control._names.focus = getFocusFieldName(name, updatedFieldArrayValuesWithKey.length - appendValue.length, options);
|
444
456
|
};
|
445
457
|
const prepend$1 = (value, options) => {
|
446
458
|
const updatedFieldArrayValuesWithKey = prepend(mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName), mapIds(convertToArrayPayload(value), keyName));
|
459
|
+
setFields(updatedFieldArrayValuesWithKey);
|
447
460
|
control._updateFieldArray(name, prepend, {
|
448
461
|
argA: fillEmptyArray(value),
|
449
462
|
}, updateValues(updatedFieldArrayValuesWithKey));
|
450
|
-
setFields(updatedFieldArrayValuesWithKey);
|
451
463
|
control._names.focus = getFocusFieldName(name, 0, options);
|
452
464
|
};
|
453
465
|
const remove = (index) => {
|
454
466
|
const updatedFieldArrayValuesWithKey = removeArrayAt(mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName), index);
|
467
|
+
setFields(updatedFieldArrayValuesWithKey);
|
455
468
|
control._updateFieldArray(name, removeArrayAt, {
|
456
469
|
argA: index,
|
457
470
|
}, updateValues(updatedFieldArrayValuesWithKey));
|
458
|
-
setFields(updatedFieldArrayValuesWithKey);
|
459
471
|
};
|
460
472
|
const insert$1 = (index, value, options) => {
|
461
473
|
const updatedFieldArrayValuesWithKey = insert(mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName), index, mapIds(convertToArrayPayload(value), keyName));
|
474
|
+
setFields(updatedFieldArrayValuesWithKey);
|
462
475
|
control._updateFieldArray(name, insert, {
|
463
476
|
argA: index,
|
464
477
|
argB: fillEmptyArray(value),
|
465
478
|
}, updateValues(updatedFieldArrayValuesWithKey));
|
466
|
-
setFields(updatedFieldArrayValuesWithKey);
|
467
479
|
control._names.focus = getFocusFieldName(name, index, options);
|
468
480
|
};
|
469
481
|
const swap = (indexA, indexB) => {
|
470
482
|
const updatedFieldArrayValuesWithKey = mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName);
|
471
483
|
swapArrayAt(updatedFieldArrayValuesWithKey, indexA, indexB);
|
484
|
+
setFields(updatedFieldArrayValuesWithKey);
|
472
485
|
control._updateFieldArray(name, swapArrayAt, {
|
473
486
|
argA: indexA,
|
474
487
|
argB: indexB,
|
475
488
|
}, updateValues(updatedFieldArrayValuesWithKey), false);
|
476
|
-
setFields(updatedFieldArrayValuesWithKey);
|
477
489
|
};
|
478
490
|
const move = (from, to) => {
|
479
491
|
const updatedFieldArrayValuesWithKey = mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName);
|
@@ -488,30 +500,20 @@ const useFieldArray = (props) => {
|
|
488
500
|
const updatedFieldArrayValuesWithKey = mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName);
|
489
501
|
const updatedFieldArrayValues = updateAt(updatedFieldArrayValuesWithKey, index, value);
|
490
502
|
_fieldIds.current = mapIds(updatedFieldArrayValues, keyName);
|
503
|
+
setFields(_fieldIds.current);
|
491
504
|
control._updateFieldArray(name, updateAt, {
|
492
505
|
argA: index,
|
493
506
|
argB: value,
|
494
507
|
}, updateValues(_fieldIds.current), true, false);
|
495
|
-
setFields(_fieldIds.current);
|
496
508
|
};
|
497
509
|
const replace = (value) => {
|
498
510
|
const updatedFieldArrayValuesWithKey = mapIds(convertToArrayPayload(value), keyName);
|
499
|
-
control._updateFieldArray(name, () => updatedFieldArrayValuesWithKey, {}, updateValues(updatedFieldArrayValuesWithKey), true, false);
|
500
511
|
setFields(updatedFieldArrayValuesWithKey);
|
512
|
+
control._updateFieldArray(name, () => updatedFieldArrayValuesWithKey, {}, updateValues(updatedFieldArrayValuesWithKey), true, false);
|
501
513
|
};
|
502
514
|
React.useEffect(() => {
|
503
515
|
control._stateFlags.action = false;
|
504
|
-
|
505
|
-
control._subjects.state.next({});
|
506
|
-
}
|
507
|
-
else {
|
508
|
-
for (const watchField of control._names.watch) {
|
509
|
-
if (name.startsWith(watchField)) {
|
510
|
-
control._subjects.state.next({});
|
511
|
-
break;
|
512
|
-
}
|
513
|
-
}
|
514
|
-
}
|
516
|
+
isWatched(name, control._names) && control._subjects.state.next({});
|
515
517
|
if (_actioned.current) {
|
516
518
|
control._executeSchema([name]).then((result) => {
|
517
519
|
const error = get(result.errors, name);
|
@@ -553,8 +555,6 @@ const useFieldArray = (props) => {
|
|
553
555
|
};
|
554
556
|
};
|
555
557
|
|
556
|
-
var isFunction = (value) => typeof value === 'function';
|
557
|
-
|
558
558
|
function cloneObject(data) {
|
559
559
|
let copy;
|
560
560
|
const isArray = Array.isArray(data);
|
@@ -1108,10 +1108,6 @@ function createFormControl(props = {}) {
|
|
1108
1108
|
clearTimeout(timer);
|
1109
1109
|
timer = window.setTimeout(() => callback(...args), wait);
|
1110
1110
|
};
|
1111
|
-
const isFieldWatched = (name, isBlurEvent) => !isBlurEvent &&
|
1112
|
-
(_names.watchAll ||
|
1113
|
-
_names.watch.has(name) ||
|
1114
|
-
_names.watch.has((name.match(/\w+/) || [])[0]));
|
1115
1111
|
const _updateValid = async (shouldSkipRender) => {
|
1116
1112
|
let isValid = false;
|
1117
1113
|
if (_proxyFormState.isValid) {
|
@@ -1380,7 +1376,7 @@ function createFormControl(props = {}) {
|
|
1380
1376
|
? setValues(name, value, options)
|
1381
1377
|
: setFieldValue(name, value, options);
|
1382
1378
|
}
|
1383
|
-
|
1379
|
+
isWatched(name, _names) && _subjects.state.next({});
|
1384
1380
|
_subjects.watch.next({
|
1385
1381
|
name,
|
1386
1382
|
});
|
@@ -1399,7 +1395,7 @@ function createFormControl(props = {}) {
|
|
1399
1395
|
!get(_formState.errors, name) &&
|
1400
1396
|
!field._f.deps) ||
|
1401
1397
|
skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, validationModeAfterSubmit, validationModeBeforeSubmit);
|
1402
|
-
const
|
1398
|
+
const watched = isWatched(name, _names, isBlurEvent);
|
1403
1399
|
if (isBlurEvent) {
|
1404
1400
|
field._f.onBlur && field._f.onBlur(event);
|
1405
1401
|
}
|
@@ -1408,7 +1404,7 @@ function createFormControl(props = {}) {
|
|
1408
1404
|
}
|
1409
1405
|
set(_formValues, name, fieldValue);
|
1410
1406
|
const fieldState = updateTouchAndDirty(name, fieldValue, isBlurEvent, false);
|
1411
|
-
const shouldRender = !isEmptyObject(fieldState) ||
|
1407
|
+
const shouldRender = !isEmptyObject(fieldState) || watched;
|
1412
1408
|
!isBlurEvent &&
|
1413
1409
|
_subjects.watch.next({
|
1414
1410
|
name,
|
@@ -1416,9 +1412,9 @@ function createFormControl(props = {}) {
|
|
1416
1412
|
});
|
1417
1413
|
if (shouldSkipValidation) {
|
1418
1414
|
return (shouldRender &&
|
1419
|
-
_subjects.state.next(Object.assign({ name }, (
|
1415
|
+
_subjects.state.next(Object.assign({ name }, (watched ? {} : fieldState))));
|
1420
1416
|
}
|
1421
|
-
!isBlurEvent &&
|
1417
|
+
!isBlurEvent && watched && _subjects.state.next({});
|
1422
1418
|
validateFields[name] = validateFields[name] ? +1 : 1;
|
1423
1419
|
_proxyFormState.isValidating &&
|
1424
1420
|
_subjects.state.next({
|
@@ -1832,9 +1828,9 @@ function useForm(props = {}) {
|
|
1832
1828
|
const control = _formControl.current.control;
|
1833
1829
|
useSubscribe({
|
1834
1830
|
subject: control._subjects.state,
|
1835
|
-
callback: (
|
1836
|
-
if (shouldRenderFormState(
|
1837
|
-
control._formState = Object.assign(Object.assign({}, control._formState),
|
1831
|
+
callback: (value) => {
|
1832
|
+
if (shouldRenderFormState(value, control._proxyFormState, true)) {
|
1833
|
+
control._formState = Object.assign(Object.assign({}, control._formState), value);
|
1838
1834
|
updateFormState(Object.assign({}, control._formState));
|
1839
1835
|
}
|
1840
1836
|
},
|