react-hook-form 7.19.3 → 7.20.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.
- 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 +84 -93
- 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/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 +5 -1
- package/package.json +19 -16
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);
|
@@ -177,47 +169,18 @@ function generateWatchOutput(names, _names, formValues, isGlobal) {
|
|
177
169
|
return formValues;
|
178
170
|
}
|
179
171
|
|
180
|
-
var isKey = (value) => /^\w*$/.test(value);
|
181
|
-
|
182
|
-
var stringToPath = (input) => compact(input.replace(/["|']|\]/g, '').split(/\.|\[/));
|
183
|
-
|
184
|
-
function set(object, path, value) {
|
185
|
-
let index = -1;
|
186
|
-
const tempPath = isKey(path) ? [path] : stringToPath(path);
|
187
|
-
const length = tempPath.length;
|
188
|
-
const lastIndex = length - 1;
|
189
|
-
while (++index < length) {
|
190
|
-
const key = tempPath[index];
|
191
|
-
let newValue = value;
|
192
|
-
if (index !== lastIndex) {
|
193
|
-
const objValue = object[key];
|
194
|
-
newValue =
|
195
|
-
isObject(objValue) || Array.isArray(objValue)
|
196
|
-
? objValue
|
197
|
-
: !isNaN(+tempPath[index + 1])
|
198
|
-
? []
|
199
|
-
: {};
|
200
|
-
}
|
201
|
-
object[key] = newValue;
|
202
|
-
object = object[key];
|
203
|
-
}
|
204
|
-
return object;
|
205
|
-
}
|
206
|
-
|
207
172
|
function useWatch(props) {
|
208
173
|
const methods = useFormContext();
|
209
|
-
const { control = methods.control, name, defaultValue, disabled, } = props || {};
|
174
|
+
const { control = methods.control, name, defaultValue, disabled, exact, } = props || {};
|
210
175
|
const _name = React.useRef(name);
|
211
176
|
_name.current = name;
|
212
177
|
useSubscribe({
|
213
178
|
disabled,
|
214
179
|
subject: control._subjects.watch,
|
215
180
|
callback: (formState) => {
|
216
|
-
if (shouldSubscribeByName(_name.current, formState.name)) {
|
181
|
+
if (shouldSubscribeByName(_name.current, formState.name, exact)) {
|
217
182
|
const fieldValues = generateWatchOutput(_name.current, control._names, formState.values || control._formValues);
|
218
|
-
updateValue(
|
219
|
-
!(isString(_name.current) &&
|
220
|
-
get(control._fields, _name.current, {})._f)
|
183
|
+
updateValue(isUndefined(_name.current)
|
221
184
|
? Object.assign({}, fieldValues) : Array.isArray(fieldValues)
|
222
185
|
? [...fieldValues]
|
223
186
|
: fieldValues);
|
@@ -236,10 +199,12 @@ function useWatch(props) {
|
|
236
199
|
function useController(props) {
|
237
200
|
const methods = useFormContext();
|
238
201
|
const { name, control = methods.control, shouldUnregister } = props;
|
202
|
+
const isArrayField = isNameInFieldArray(control._names.array, name);
|
239
203
|
const value = useWatch({
|
240
204
|
control,
|
241
205
|
name,
|
242
206
|
defaultValue: get(control._formValues, name, get(control._defaultValues, name, props.defaultValue)),
|
207
|
+
exact: !isArrayField,
|
243
208
|
});
|
244
209
|
const formState = useFormState({
|
245
210
|
control,
|
@@ -258,7 +223,7 @@ function useController(props) {
|
|
258
223
|
updateMounted(name, true);
|
259
224
|
return () => {
|
260
225
|
const _shouldUnregisterField = control._options.shouldUnregister || shouldUnregister;
|
261
|
-
if (
|
226
|
+
if (isArrayField
|
262
227
|
? _shouldUnregisterField && !control._stateFlags.action
|
263
228
|
: _shouldUnregisterField) {
|
264
229
|
control.unregister(name, { keepDefaultValue: true });
|
@@ -267,7 +232,7 @@ function useController(props) {
|
|
267
232
|
updateMounted(name, false);
|
268
233
|
}
|
269
234
|
};
|
270
|
-
}, [name, control, shouldUnregister]);
|
235
|
+
}, [name, control, isArrayField, shouldUnregister]);
|
271
236
|
return {
|
272
237
|
field: {
|
273
238
|
onChange: (event) => {
|
@@ -282,7 +247,7 @@ function useController(props) {
|
|
282
247
|
onBlur: () => {
|
283
248
|
registerProps.onBlur({
|
284
249
|
target: {
|
285
|
-
value,
|
250
|
+
value: get(control._formValues, name),
|
286
251
|
name: name,
|
287
252
|
},
|
288
253
|
type: EVENTS.BLUR,
|
@@ -316,6 +281,33 @@ const Controller = (props) => props.render(useController(props));
|
|
316
281
|
var appendErrors = (name, validateAllFieldCriteria, errors, type, message) => validateAllFieldCriteria
|
317
282
|
? Object.assign(Object.assign({}, errors[name]), { types: Object.assign(Object.assign({}, (errors[name] && errors[name].types ? errors[name].types : {})), { [type]: message || true }) }) : {};
|
318
283
|
|
284
|
+
var isKey = (value) => /^\w*$/.test(value);
|
285
|
+
|
286
|
+
var stringToPath = (input) => compact(input.replace(/["|']|\]/g, '').split(/\.|\[/));
|
287
|
+
|
288
|
+
function set(object, path, value) {
|
289
|
+
let index = -1;
|
290
|
+
const tempPath = isKey(path) ? [path] : stringToPath(path);
|
291
|
+
const length = tempPath.length;
|
292
|
+
const lastIndex = length - 1;
|
293
|
+
while (++index < length) {
|
294
|
+
const key = tempPath[index];
|
295
|
+
let newValue = value;
|
296
|
+
if (index !== lastIndex) {
|
297
|
+
const objValue = object[key];
|
298
|
+
newValue =
|
299
|
+
isObject(objValue) || Array.isArray(objValue)
|
300
|
+
? objValue
|
301
|
+
: !isNaN(+tempPath[index + 1])
|
302
|
+
? []
|
303
|
+
: {};
|
304
|
+
}
|
305
|
+
object[key] = newValue;
|
306
|
+
object = object[key];
|
307
|
+
}
|
308
|
+
return object;
|
309
|
+
}
|
310
|
+
|
319
311
|
const focusFieldBy = (fields, callback, fieldsNames) => {
|
320
312
|
for (const key of fieldsNames || Object.keys(fields)) {
|
321
313
|
const field = get(fields, key);
|
@@ -343,6 +335,12 @@ var getFocusFieldName = (name, index, options = {}) => options.shouldFocus || is
|
|
343
335
|
`${name}.${isUndefined(options.focusIndex) ? index : options.focusIndex}.`
|
344
336
|
: '';
|
345
337
|
|
338
|
+
var isWatched = (name, _names, isBlurEvent) => !isBlurEvent &&
|
339
|
+
(_names.watchAll ||
|
340
|
+
_names.watch.has(name) ||
|
341
|
+
[..._names.watch].some((watchName) => name.startsWith(watchName) &&
|
342
|
+
/^\.\w+/.test(name.slice(watchName.length))));
|
343
|
+
|
346
344
|
var mapCurrentIds = (values, _fieldIds, keyName) => values.map((value, index) => {
|
347
345
|
const output = _fieldIds.current[index];
|
348
346
|
return Object.assign(Object.assign({}, value), (output ? { [keyName]: output[keyName] } : {}));
|
@@ -433,12 +431,12 @@ const useFieldArray = (props) => {
|
|
433
431
|
const updatedFieldArrayValues = omitKeys(updatedFieldArrayValuesWithKey, keyName);
|
434
432
|
_actioned.current = true;
|
435
433
|
set(control._formValues, name, updatedFieldArrayValues);
|
436
|
-
setFields(updatedFieldArrayValuesWithKey);
|
437
434
|
return updatedFieldArrayValues;
|
438
435
|
}, [control, name, keyName]);
|
439
436
|
const append$1 = (value, options) => {
|
440
437
|
const appendValue = convertToArrayPayload(value);
|
441
438
|
const updatedFieldArrayValuesWithKey = append(mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName), mapIds(appendValue, keyName));
|
439
|
+
setFields(updatedFieldArrayValuesWithKey);
|
442
440
|
control._updateFieldArray(name, append, {
|
443
441
|
argA: fillEmptyArray(value),
|
444
442
|
}, updateValues(updatedFieldArrayValuesWithKey));
|
@@ -446,6 +444,7 @@ const useFieldArray = (props) => {
|
|
446
444
|
};
|
447
445
|
const prepend$1 = (value, options) => {
|
448
446
|
const updatedFieldArrayValuesWithKey = prepend(mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName), mapIds(convertToArrayPayload(value), keyName));
|
447
|
+
setFields(updatedFieldArrayValuesWithKey);
|
449
448
|
control._updateFieldArray(name, prepend, {
|
450
449
|
argA: fillEmptyArray(value),
|
451
450
|
}, updateValues(updatedFieldArrayValuesWithKey));
|
@@ -453,12 +452,14 @@ const useFieldArray = (props) => {
|
|
453
452
|
};
|
454
453
|
const remove = (index) => {
|
455
454
|
const updatedFieldArrayValuesWithKey = removeArrayAt(mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName), index);
|
455
|
+
setFields(updatedFieldArrayValuesWithKey);
|
456
456
|
control._updateFieldArray(name, removeArrayAt, {
|
457
457
|
argA: index,
|
458
458
|
}, updateValues(updatedFieldArrayValuesWithKey));
|
459
459
|
};
|
460
460
|
const insert$1 = (index, value, options) => {
|
461
461
|
const updatedFieldArrayValuesWithKey = insert(mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName), index, mapIds(convertToArrayPayload(value), keyName));
|
462
|
+
setFields(updatedFieldArrayValuesWithKey);
|
462
463
|
control._updateFieldArray(name, insert, {
|
463
464
|
argA: index,
|
464
465
|
argB: fillEmptyArray(value),
|
@@ -468,6 +469,7 @@ const useFieldArray = (props) => {
|
|
468
469
|
const swap = (indexA, indexB) => {
|
469
470
|
const updatedFieldArrayValuesWithKey = mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName);
|
470
471
|
swapArrayAt(updatedFieldArrayValuesWithKey, indexA, indexB);
|
472
|
+
setFields(updatedFieldArrayValuesWithKey);
|
471
473
|
control._updateFieldArray(name, swapArrayAt, {
|
472
474
|
argA: indexA,
|
473
475
|
argB: indexB,
|
@@ -480,11 +482,13 @@ const useFieldArray = (props) => {
|
|
480
482
|
argA: from,
|
481
483
|
argB: to,
|
482
484
|
}, updateValues(updatedFieldArrayValuesWithKey), false);
|
485
|
+
setFields(updatedFieldArrayValuesWithKey);
|
483
486
|
};
|
484
487
|
const update = (index, value) => {
|
485
488
|
const updatedFieldArrayValuesWithKey = mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName);
|
486
489
|
const updatedFieldArrayValues = updateAt(updatedFieldArrayValuesWithKey, index, value);
|
487
490
|
_fieldIds.current = mapIds(updatedFieldArrayValues, keyName);
|
491
|
+
setFields(_fieldIds.current);
|
488
492
|
control._updateFieldArray(name, updateAt, {
|
489
493
|
argA: index,
|
490
494
|
argB: value,
|
@@ -492,21 +496,12 @@ const useFieldArray = (props) => {
|
|
492
496
|
};
|
493
497
|
const replace = (value) => {
|
494
498
|
const updatedFieldArrayValuesWithKey = mapIds(convertToArrayPayload(value), keyName);
|
499
|
+
setFields(updatedFieldArrayValuesWithKey);
|
495
500
|
control._updateFieldArray(name, () => updatedFieldArrayValuesWithKey, {}, updateValues(updatedFieldArrayValuesWithKey), true, false);
|
496
501
|
};
|
497
502
|
React.useEffect(() => {
|
498
503
|
control._stateFlags.action = false;
|
499
|
-
|
500
|
-
control._subjects.state.next({});
|
501
|
-
}
|
502
|
-
else {
|
503
|
-
for (const watchField of control._names.watch) {
|
504
|
-
if (name.startsWith(watchField)) {
|
505
|
-
control._subjects.state.next({});
|
506
|
-
break;
|
507
|
-
}
|
508
|
-
}
|
509
|
-
}
|
504
|
+
isWatched(name, control._names) && control._subjects.state.next({});
|
510
505
|
if (_actioned.current) {
|
511
506
|
control._executeSchema([name]).then((result) => {
|
512
507
|
const error = get(result.errors, name);
|
@@ -1103,10 +1098,6 @@ function createFormControl(props = {}) {
|
|
1103
1098
|
clearTimeout(timer);
|
1104
1099
|
timer = window.setTimeout(() => callback(...args), wait);
|
1105
1100
|
};
|
1106
|
-
const isFieldWatched = (name, isBlurEvent) => !isBlurEvent &&
|
1107
|
-
(_names.watchAll ||
|
1108
|
-
_names.watch.has(name) ||
|
1109
|
-
_names.watch.has((name.match(/\w+/) || [])[0]));
|
1110
1101
|
const _updateValid = async (shouldSkipRender) => {
|
1111
1102
|
let isValid = false;
|
1112
1103
|
if (_proxyFormState.isValid) {
|
@@ -1375,7 +1366,7 @@ function createFormControl(props = {}) {
|
|
1375
1366
|
? setValues(name, value, options)
|
1376
1367
|
: setFieldValue(name, value, options);
|
1377
1368
|
}
|
1378
|
-
|
1369
|
+
isWatched(name, _names) && _subjects.state.next({});
|
1379
1370
|
_subjects.watch.next({
|
1380
1371
|
name,
|
1381
1372
|
});
|
@@ -1394,7 +1385,7 @@ function createFormControl(props = {}) {
|
|
1394
1385
|
!get(_formState.errors, name) &&
|
1395
1386
|
!field._f.deps) ||
|
1396
1387
|
skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, validationModeAfterSubmit, validationModeBeforeSubmit);
|
1397
|
-
const
|
1388
|
+
const watched = isWatched(name, _names, isBlurEvent);
|
1398
1389
|
if (isBlurEvent) {
|
1399
1390
|
field._f.onBlur && field._f.onBlur(event);
|
1400
1391
|
}
|
@@ -1403,7 +1394,7 @@ function createFormControl(props = {}) {
|
|
1403
1394
|
}
|
1404
1395
|
set(_formValues, name, fieldValue);
|
1405
1396
|
const fieldState = updateTouchAndDirty(name, fieldValue, isBlurEvent, false);
|
1406
|
-
const shouldRender = !isEmptyObject(fieldState) ||
|
1397
|
+
const shouldRender = !isEmptyObject(fieldState) || watched;
|
1407
1398
|
!isBlurEvent &&
|
1408
1399
|
_subjects.watch.next({
|
1409
1400
|
name,
|
@@ -1411,9 +1402,9 @@ function createFormControl(props = {}) {
|
|
1411
1402
|
});
|
1412
1403
|
if (shouldSkipValidation) {
|
1413
1404
|
return (shouldRender &&
|
1414
|
-
_subjects.state.next(Object.assign({ name }, (
|
1405
|
+
_subjects.state.next(Object.assign({ name }, (watched ? {} : fieldState))));
|
1415
1406
|
}
|
1416
|
-
!isBlurEvent &&
|
1407
|
+
!isBlurEvent && watched && _subjects.state.next({});
|
1417
1408
|
validateFields[name] = validateFields[name] ? +1 : 1;
|
1418
1409
|
_proxyFormState.isValidating &&
|
1419
1410
|
_subjects.state.next({
|
@@ -1827,9 +1818,9 @@ function useForm(props = {}) {
|
|
1827
1818
|
const control = _formControl.current.control;
|
1828
1819
|
useSubscribe({
|
1829
1820
|
subject: control._subjects.state,
|
1830
|
-
callback: (
|
1831
|
-
if (shouldRenderFormState(
|
1832
|
-
control._formState = Object.assign(Object.assign({}, control._formState),
|
1821
|
+
callback: (value) => {
|
1822
|
+
if (shouldRenderFormState(value, control._proxyFormState, true)) {
|
1823
|
+
control._formState = Object.assign(Object.assign({}, control._formState), value);
|
1833
1824
|
updateFormState(Object.assign({}, control._formState));
|
1834
1825
|
}
|
1835
1826
|
},
|