react-hook-form 7.72.0 → 7.73.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/README.md +3 -19
- package/dist/__tests__/nested-null.test.d.ts +2 -0
- package/dist/__tests__/nested-null.test.d.ts.map +1 -0
- package/dist/form.d.ts.map +1 -1
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.mjs +123 -84
- package/dist/index.esm.mjs.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/dist/logic/createFormControl.d.ts.map +1 -1
- package/dist/logic/isNameInFieldArray.d.ts.map +1 -1
- package/dist/react-server.esm.mjs +64 -37
- package/dist/react-server.esm.mjs.map +1 -1
- package/dist/types/form.d.ts +1 -0
- package/dist/types/form.d.ts.map +1 -1
- package/dist/useFieldArray.d.ts.map +1 -1
- package/dist/useFormContext.d.ts.map +1 -1
- package/dist/utils/deepEqual.d.ts +1 -1
- package/dist/utils/deepEqual.d.ts.map +1 -1
- package/dist/utils/unset.d.ts.map +1 -1
- package/package.json +20 -20
package/dist/index.esm.mjs
CHANGED
|
@@ -18,9 +18,9 @@ var getEventValue = (event) => isObject(event) && event.target
|
|
|
18
18
|
: event.target.value
|
|
19
19
|
: event;
|
|
20
20
|
|
|
21
|
-
var
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
var isNameInFieldArray = (names, name) => name
|
|
22
|
+
.split('.')
|
|
23
|
+
.some((part, index, arr) => !isNaN(Number(part)) && names.has(arr.slice(0, index).join('.')));
|
|
24
24
|
|
|
25
25
|
var isPlainObject = (tempObject) => {
|
|
26
26
|
const prototypeCopy = tempObject.constructor && tempObject.constructor.prototype;
|
|
@@ -64,7 +64,10 @@ var get = (object, path, defaultValue) => {
|
|
|
64
64
|
if (!path || !isObject(object)) {
|
|
65
65
|
return defaultValue;
|
|
66
66
|
}
|
|
67
|
-
const
|
|
67
|
+
const paths = isKey(path) ? [path] : stringToPath(path);
|
|
68
|
+
const result = paths.reduce((result, key) => {
|
|
69
|
+
return isNullOrUndefined(result) ? undefined : result[key];
|
|
70
|
+
}, object);
|
|
68
71
|
return isUndefined(result) || result === object
|
|
69
72
|
? isUndefined(object[path])
|
|
70
73
|
? defaultValue
|
|
@@ -239,7 +242,10 @@ var generateWatchOutput = (names, _names, formValues, isGlobal, defaultValue) =>
|
|
|
239
242
|
|
|
240
243
|
var isPrimitive = (value) => isNullOrUndefined(value) || !isObjectType(value);
|
|
241
244
|
|
|
242
|
-
function deepEqual(object1, object2,
|
|
245
|
+
function deepEqual(object1, object2, visited = new WeakSet()) {
|
|
246
|
+
if (object1 === object2) {
|
|
247
|
+
return true;
|
|
248
|
+
}
|
|
243
249
|
if (isPrimitive(object1) || isPrimitive(object2)) {
|
|
244
250
|
return Object.is(object1, object2);
|
|
245
251
|
}
|
|
@@ -251,22 +257,22 @@ function deepEqual(object1, object2, _internal_visited = new WeakSet()) {
|
|
|
251
257
|
if (keys1.length !== keys2.length) {
|
|
252
258
|
return false;
|
|
253
259
|
}
|
|
254
|
-
if (
|
|
260
|
+
if (visited.has(object1) || visited.has(object2)) {
|
|
255
261
|
return true;
|
|
256
262
|
}
|
|
257
|
-
|
|
258
|
-
|
|
263
|
+
visited.add(object1);
|
|
264
|
+
visited.add(object2);
|
|
259
265
|
for (const key of keys1) {
|
|
260
266
|
const val1 = object1[key];
|
|
261
|
-
if (!
|
|
267
|
+
if (!(key in object2)) {
|
|
262
268
|
return false;
|
|
263
269
|
}
|
|
264
270
|
if (key !== 'ref') {
|
|
265
271
|
const val2 = object2[key];
|
|
266
272
|
if ((isDateObject(val1) && isDateObject(val2)) ||
|
|
267
|
-
(isObject(val1)
|
|
268
|
-
|
|
269
|
-
? !deepEqual(val1, val2,
|
|
273
|
+
((isObject(val1) || Array.isArray(val1)) &&
|
|
274
|
+
(isObject(val2) || Array.isArray(val2)))
|
|
275
|
+
? !deepEqual(val1, val2, visited)
|
|
270
276
|
: !Object.is(val1, val2)) {
|
|
271
277
|
return false;
|
|
272
278
|
}
|
|
@@ -640,42 +646,43 @@ const useFormContext = () => React.useContext(HookFormContext);
|
|
|
640
646
|
*/
|
|
641
647
|
const FormProvider = (props) => {
|
|
642
648
|
const { children, watch, getValues, getFieldState, setError, clearErrors, setValue, trigger, formState, resetField, reset, handleSubmit, unregister, control, register, setFocus, subscribe, } = props;
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
649
|
+
const memoizedValue = React.useMemo(() => ({
|
|
650
|
+
watch,
|
|
651
|
+
getValues,
|
|
652
|
+
getFieldState,
|
|
653
|
+
setError,
|
|
654
|
+
clearErrors,
|
|
655
|
+
setValue,
|
|
656
|
+
trigger,
|
|
657
|
+
formState,
|
|
658
|
+
resetField,
|
|
659
|
+
reset,
|
|
660
|
+
handleSubmit,
|
|
661
|
+
unregister,
|
|
662
|
+
control,
|
|
663
|
+
register,
|
|
664
|
+
setFocus,
|
|
665
|
+
subscribe,
|
|
666
|
+
}), [
|
|
667
|
+
clearErrors,
|
|
668
|
+
control,
|
|
669
|
+
formState,
|
|
670
|
+
getFieldState,
|
|
671
|
+
getValues,
|
|
672
|
+
handleSubmit,
|
|
673
|
+
register,
|
|
674
|
+
reset,
|
|
675
|
+
resetField,
|
|
676
|
+
setError,
|
|
677
|
+
setFocus,
|
|
678
|
+
setValue,
|
|
679
|
+
subscribe,
|
|
680
|
+
trigger,
|
|
681
|
+
unregister,
|
|
682
|
+
watch,
|
|
683
|
+
]);
|
|
684
|
+
return (React.createElement(HookFormContext.Provider, { value: memoizedValue },
|
|
685
|
+
React.createElement(HookFormControlContext.Provider, { value: memoizedValue.control }, children)));
|
|
679
686
|
};
|
|
680
687
|
|
|
681
688
|
const POST_REQUEST = 'post';
|
|
@@ -705,7 +712,7 @@ function Form(props) {
|
|
|
705
712
|
const methods = useFormContext();
|
|
706
713
|
const [mounted, setMounted] = React.useState(false);
|
|
707
714
|
const { control = methods.control, onSubmit, children, action, method = POST_REQUEST, headers, encType, onError, render, onSuccess, validateStatus, ...rest } = props;
|
|
708
|
-
const submit = async (event) => {
|
|
715
|
+
const submit = React.useCallback(async (event) => {
|
|
709
716
|
let hasError = false;
|
|
710
717
|
let type = '';
|
|
711
718
|
await control.handleSubmit(async (data) => {
|
|
@@ -715,7 +722,7 @@ function Form(props) {
|
|
|
715
722
|
formDataJson = JSON.stringify(data);
|
|
716
723
|
}
|
|
717
724
|
catch (_a) { }
|
|
718
|
-
const flattenFormValues = flatten(
|
|
725
|
+
const flattenFormValues = flatten(data);
|
|
719
726
|
for (const key in flattenFormValues) {
|
|
720
727
|
formData.append(key, flattenFormValues[key]);
|
|
721
728
|
}
|
|
@@ -762,15 +769,25 @@ function Form(props) {
|
|
|
762
769
|
}
|
|
763
770
|
}
|
|
764
771
|
})(event);
|
|
765
|
-
if (hasError &&
|
|
766
|
-
|
|
772
|
+
if (hasError && control) {
|
|
773
|
+
control._subjects.state.next({
|
|
767
774
|
isSubmitSuccessful: false,
|
|
768
775
|
});
|
|
769
|
-
|
|
776
|
+
control.setError('root.server', {
|
|
770
777
|
type,
|
|
771
778
|
});
|
|
772
779
|
}
|
|
773
|
-
}
|
|
780
|
+
}, [
|
|
781
|
+
control,
|
|
782
|
+
onSubmit,
|
|
783
|
+
method,
|
|
784
|
+
action,
|
|
785
|
+
headers,
|
|
786
|
+
encType,
|
|
787
|
+
validateStatus,
|
|
788
|
+
onError,
|
|
789
|
+
onSuccess,
|
|
790
|
+
]);
|
|
774
791
|
React.useEffect(() => {
|
|
775
792
|
setMounted(true);
|
|
776
793
|
}, []);
|
|
@@ -879,6 +896,10 @@ function isEmptyArray(obj) {
|
|
|
879
896
|
return true;
|
|
880
897
|
}
|
|
881
898
|
function unset(object, path) {
|
|
899
|
+
if (isString(path) && Object.prototype.hasOwnProperty.call(object, path)) {
|
|
900
|
+
delete object[path];
|
|
901
|
+
return object;
|
|
902
|
+
}
|
|
882
903
|
const paths = Array.isArray(path)
|
|
883
904
|
? path
|
|
884
905
|
: isKey(path)
|
|
@@ -1014,6 +1035,8 @@ function getFieldValue(_f) {
|
|
|
1014
1035
|
return getFieldValueAs(isUndefined(ref.value) ? _f.ref.value : ref.value, _f);
|
|
1015
1036
|
}
|
|
1016
1037
|
|
|
1038
|
+
var getNodeParentName = (name) => name.substring(0, name.search(/\.\d+(\.|$)/)) || name;
|
|
1039
|
+
|
|
1017
1040
|
var getResolverOptions = (fieldsNames, _fields, criteriaMode, shouldUseNativeValidation) => {
|
|
1018
1041
|
const fields = {};
|
|
1019
1042
|
for (const name of fieldsNames) {
|
|
@@ -1420,6 +1443,7 @@ function createFormControl(props = {}) {
|
|
|
1420
1443
|
unMount: new Set(),
|
|
1421
1444
|
array: new Set(),
|
|
1422
1445
|
watch: new Set(),
|
|
1446
|
+
registerName: new Set(),
|
|
1423
1447
|
};
|
|
1424
1448
|
let delayErrorCallback;
|
|
1425
1449
|
let timer = 0;
|
|
@@ -1493,6 +1517,11 @@ function createFormControl(props = {}) {
|
|
|
1493
1517
|
});
|
|
1494
1518
|
}
|
|
1495
1519
|
};
|
|
1520
|
+
const _updateDirtyFields = (name) => {
|
|
1521
|
+
const fullDirtyFields = getDirtyFields(_defaultValues, _formValues);
|
|
1522
|
+
const rootName = getNodeParentName(name);
|
|
1523
|
+
set(_formState.dirtyFields, rootName, get(fullDirtyFields, rootName));
|
|
1524
|
+
};
|
|
1496
1525
|
const _setFieldArray = (name, values = [], method, args, shouldSetValues = true, shouldUpdateFieldsAndState = true) => {
|
|
1497
1526
|
if (args && method && !_options.disabled) {
|
|
1498
1527
|
_state.action = true;
|
|
@@ -1514,9 +1543,7 @@ function createFormControl(props = {}) {
|
|
|
1514
1543
|
shouldSetValues && set(_formState.touchedFields, name, touchedFields);
|
|
1515
1544
|
}
|
|
1516
1545
|
if (_proxyFormState.dirtyFields || _proxySubscribeFormState.dirtyFields) {
|
|
1517
|
-
|
|
1518
|
-
const rootName = getNodeParentName(name);
|
|
1519
|
-
set(_formState.dirtyFields, rootName, get(fullDirtyFields, rootName));
|
|
1546
|
+
_updateDirtyFields(name);
|
|
1520
1547
|
}
|
|
1521
1548
|
_subjects.state.next({
|
|
1522
1549
|
name,
|
|
@@ -1834,41 +1861,47 @@ function createFormControl(props = {}) {
|
|
|
1834
1861
|
const field = get(_fields, name);
|
|
1835
1862
|
const isFieldArray = _names.array.has(name);
|
|
1836
1863
|
const cloneValue = cloneObject(value);
|
|
1864
|
+
const previousValue = get(_formValues, name);
|
|
1865
|
+
const isValueUnchanged = deepEqual(previousValue, cloneValue);
|
|
1837
1866
|
set(_formValues, name, cloneValue);
|
|
1838
1867
|
if (isFieldArray) {
|
|
1839
1868
|
_subjects.array.next({
|
|
1840
1869
|
name,
|
|
1841
1870
|
values: cloneObject(_formValues),
|
|
1842
1871
|
});
|
|
1843
|
-
if (
|
|
1844
|
-
|
|
1845
|
-
_proxySubscribeFormState.isDirty ||
|
|
1846
|
-
_proxySubscribeFormState.dirtyFields) &&
|
|
1847
|
-
options.shouldDirty) {
|
|
1872
|
+
if (options.shouldDirty) {
|
|
1873
|
+
_updateDirtyFields(name);
|
|
1848
1874
|
_subjects.state.next({
|
|
1849
1875
|
name,
|
|
1850
|
-
dirtyFields:
|
|
1876
|
+
dirtyFields: _formState.dirtyFields,
|
|
1851
1877
|
isDirty: _getDirty(name, cloneValue),
|
|
1852
1878
|
});
|
|
1853
1879
|
}
|
|
1854
1880
|
}
|
|
1855
1881
|
else {
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
values: cloneObject(_formValues),
|
|
1865
|
-
});
|
|
1882
|
+
const isEmpty = (Array.isArray(cloneValue) && !cloneValue.length) ||
|
|
1883
|
+
isEmptyObject(cloneValue);
|
|
1884
|
+
if (!field || field._f || isNullOrUndefined(cloneValue) || isEmpty) {
|
|
1885
|
+
setFieldValue(name, cloneValue, options);
|
|
1886
|
+
}
|
|
1887
|
+
else {
|
|
1888
|
+
setValues(name, cloneValue, options);
|
|
1889
|
+
}
|
|
1866
1890
|
}
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1891
|
+
if (!isValueUnchanged) {
|
|
1892
|
+
if (isWatched(name, _names)) {
|
|
1893
|
+
_subjects.state.next({
|
|
1894
|
+
..._formState,
|
|
1895
|
+
name,
|
|
1896
|
+
values: cloneObject(_formValues),
|
|
1897
|
+
});
|
|
1898
|
+
}
|
|
1899
|
+
else {
|
|
1900
|
+
_subjects.state.next({
|
|
1901
|
+
name: _state.mount ? name : undefined,
|
|
1902
|
+
values: cloneObject(_formValues),
|
|
1903
|
+
});
|
|
1904
|
+
}
|
|
1872
1905
|
}
|
|
1873
1906
|
};
|
|
1874
1907
|
const onChange = async (event) => {
|
|
@@ -2087,15 +2120,16 @@ function createFormControl(props = {}) {
|
|
|
2087
2120
|
const watch = (name, defaultValue) => isFunction(name)
|
|
2088
2121
|
? _subjects.state.subscribe({
|
|
2089
2122
|
next: (payload) => 'values' in payload &&
|
|
2090
|
-
name(_getWatch(undefined, defaultValue), payload),
|
|
2123
|
+
name(payload.values || _getWatch(undefined, defaultValue), payload),
|
|
2091
2124
|
})
|
|
2092
2125
|
: _getWatch(name, defaultValue, true);
|
|
2093
2126
|
const _subscribe = (props) => _subjects.state.subscribe({
|
|
2094
2127
|
next: (formState) => {
|
|
2095
2128
|
if (shouldSubscribeByName(props.name, formState.name, props.exact) &&
|
|
2096
2129
|
shouldRenderFormState(formState, props.formState || _proxyFormState, _setFormState, props.reRenderRoot)) {
|
|
2130
|
+
const snapshot = { ..._formValues };
|
|
2097
2131
|
props.callback({
|
|
2098
|
-
values:
|
|
2132
|
+
values: snapshot,
|
|
2099
2133
|
..._formState,
|
|
2100
2134
|
...formState,
|
|
2101
2135
|
defaultValues: _defaultValues,
|
|
@@ -2157,6 +2191,7 @@ function createFormControl(props = {}) {
|
|
|
2157
2191
|
const register = (name, options = {}) => {
|
|
2158
2192
|
let field = get(_fields, name);
|
|
2159
2193
|
const disabledIsDefined = isBoolean(options.disabled) || isBoolean(_options.disabled);
|
|
2194
|
+
const shouldRevalidateRemount = !_names.registerName.has(name) && field && field._f && !field._f.mount;
|
|
2160
2195
|
set(_fields, name, {
|
|
2161
2196
|
...(field || {}),
|
|
2162
2197
|
_f: {
|
|
@@ -2167,7 +2202,7 @@ function createFormControl(props = {}) {
|
|
|
2167
2202
|
},
|
|
2168
2203
|
});
|
|
2169
2204
|
_names.mount.add(name);
|
|
2170
|
-
if (field) {
|
|
2205
|
+
if (field && !shouldRevalidateRemount) {
|
|
2171
2206
|
_setDisabledField({
|
|
2172
2207
|
disabled: isBoolean(options.disabled)
|
|
2173
2208
|
? options.disabled
|
|
@@ -2197,7 +2232,9 @@ function createFormControl(props = {}) {
|
|
|
2197
2232
|
onBlur: onChange,
|
|
2198
2233
|
ref: (ref) => {
|
|
2199
2234
|
if (ref) {
|
|
2235
|
+
_names.registerName.add(name);
|
|
2200
2236
|
register(name, options);
|
|
2237
|
+
_names.registerName.delete(name);
|
|
2201
2238
|
field = get(_fields, name);
|
|
2202
2239
|
const fieldRef = isUndefined(ref.value)
|
|
2203
2240
|
? ref.querySelectorAll
|
|
@@ -2410,6 +2447,7 @@ function createFormControl(props = {}) {
|
|
|
2410
2447
|
mount: keepStateOptions.keepDirtyValues ? _names.mount : new Set(),
|
|
2411
2448
|
unMount: new Set(),
|
|
2412
2449
|
array: new Set(),
|
|
2450
|
+
registerName: new Set(),
|
|
2413
2451
|
disabled: new Set(),
|
|
2414
2452
|
watch: new Set(),
|
|
2415
2453
|
watchAll: false,
|
|
@@ -2800,10 +2838,11 @@ function useFieldArray(props) {
|
|
|
2800
2838
|
control._subjects.state.next({
|
|
2801
2839
|
...control._formState,
|
|
2802
2840
|
});
|
|
2841
|
+
const validationModes = getValidationModes(control._options.mode);
|
|
2803
2842
|
if (_actioned.current &&
|
|
2804
|
-
(!
|
|
2805
|
-
|
|
2806
|
-
!
|
|
2843
|
+
(!validationModes.isOnSubmit || control._formState.isSubmitted) &&
|
|
2844
|
+
!getValidationModes(control._options.reValidateMode).isOnSubmit &&
|
|
2845
|
+
!validationModes.isOnBlur) {
|
|
2807
2846
|
if (control._options.resolver) {
|
|
2808
2847
|
control._runSchema([name]).then((result) => {
|
|
2809
2848
|
control._updateIsValidating([name]);
|