react-hook-form 7.56.0 → 7.56.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/README.md +30 -28
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.mjs +94 -104
- 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/react-server.esm.mjs +1 -1
- package/dist/react-server.esm.mjs.map +1 -1
- package/dist/useController.d.ts.map +1 -1
- package/dist/useForm.d.ts.map +1 -1
- package/dist/useIsomorphicLayoutEffect.d.ts +3 -0
- package/dist/useIsomorphicLayoutEffect.d.ts.map +1 -0
- package/package.json +2 -2
- package/dist/useDeepEqualEffect.d.ts +0 -3
- package/dist/useDeepEqualEffect.d.ts.map +0 -1
package/dist/index.esm.mjs
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
import
|
1
|
+
import * as React from 'react';
|
2
|
+
import React__default from 'react';
|
2
3
|
|
3
4
|
var isCheckBoxInput = (element) => element.type === 'checkbox';
|
4
5
|
|
@@ -130,7 +131,7 @@ const INPUT_VALIDATION_RULES = {
|
|
130
131
|
validate: 'validate',
|
131
132
|
};
|
132
133
|
|
133
|
-
const HookFormContext =
|
134
|
+
const HookFormContext = React__default.createContext(null);
|
134
135
|
/**
|
135
136
|
* This custom hook allows you to access the form context. useFormContext is intended to be used in deeply nested structures, where it would become inconvenient to pass the context as a prop. To be used with {@link FormProvider}.
|
136
137
|
*
|
@@ -161,7 +162,7 @@ const HookFormContext = React.createContext(null);
|
|
161
162
|
* }
|
162
163
|
* ```
|
163
164
|
*/
|
164
|
-
const useFormContext = () =>
|
165
|
+
const useFormContext = () => React__default.useContext(HookFormContext);
|
165
166
|
/**
|
166
167
|
* A provider component that propagates the `useForm` methods to all children components via [React Context](https://reactjs.org/docs/context.html) API. To be used with {@link useFormContext}.
|
167
168
|
*
|
@@ -194,7 +195,7 @@ const useFormContext = () => React.useContext(HookFormContext);
|
|
194
195
|
*/
|
195
196
|
const FormProvider = (props) => {
|
196
197
|
const { children, ...data } = props;
|
197
|
-
return (
|
198
|
+
return (React__default.createElement(HookFormContext.Provider, { value: data }, children));
|
198
199
|
};
|
199
200
|
|
200
201
|
var getProxyFormState = (formState, control, localProxyFormState, isRoot = true) => {
|
@@ -216,47 +217,7 @@ var getProxyFormState = (formState, control, localProxyFormState, isRoot = true)
|
|
216
217
|
return result;
|
217
218
|
};
|
218
219
|
|
219
|
-
|
220
|
-
|
221
|
-
function deepEqual(object1, object2) {
|
222
|
-
if (isPrimitive(object1) || isPrimitive(object2)) {
|
223
|
-
return object1 === object2;
|
224
|
-
}
|
225
|
-
if (isDateObject(object1) && isDateObject(object2)) {
|
226
|
-
return object1.getTime() === object2.getTime();
|
227
|
-
}
|
228
|
-
const keys1 = Object.keys(object1);
|
229
|
-
const keys2 = Object.keys(object2);
|
230
|
-
if (keys1.length !== keys2.length) {
|
231
|
-
return false;
|
232
|
-
}
|
233
|
-
for (const key of keys1) {
|
234
|
-
const val1 = object1[key];
|
235
|
-
if (!keys2.includes(key)) {
|
236
|
-
return false;
|
237
|
-
}
|
238
|
-
if (key !== 'ref') {
|
239
|
-
const val2 = object2[key];
|
240
|
-
if ((isDateObject(val1) && isDateObject(val2)) ||
|
241
|
-
(isObject(val1) && isObject(val2)) ||
|
242
|
-
(Array.isArray(val1) && Array.isArray(val2))
|
243
|
-
? !deepEqual(val1, val2)
|
244
|
-
: val1 !== val2) {
|
245
|
-
return false;
|
246
|
-
}
|
247
|
-
}
|
248
|
-
}
|
249
|
-
return true;
|
250
|
-
}
|
251
|
-
|
252
|
-
const useDeepEqualEffect = (effect, deps) => {
|
253
|
-
const ref = useRef(deps);
|
254
|
-
if (!deepEqual(deps, ref.current)) {
|
255
|
-
ref.current = deps;
|
256
|
-
}
|
257
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
258
|
-
useEffect(effect, ref.current);
|
259
|
-
};
|
220
|
+
const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
|
260
221
|
|
261
222
|
/**
|
262
223
|
* This custom hook allows you to subscribe to each form state, and isolate the re-render at the custom hook level. It has its scope in terms of form state subscription, so it would not affect other useFormState and useForm. Using this hook can reduce the re-render impact on large and complex form application.
|
@@ -291,8 +252,8 @@ const useDeepEqualEffect = (effect, deps) => {
|
|
291
252
|
function useFormState(props) {
|
292
253
|
const methods = useFormContext();
|
293
254
|
const { control = methods.control, disabled, name, exact } = props || {};
|
294
|
-
const [formState, updateFormState] =
|
295
|
-
const _localProxyFormState =
|
255
|
+
const [formState, updateFormState] = React__default.useState(control._formState);
|
256
|
+
const _localProxyFormState = React__default.useRef({
|
296
257
|
isDirty: false,
|
297
258
|
isLoading: false,
|
298
259
|
dirtyFields: false,
|
@@ -302,7 +263,7 @@ function useFormState(props) {
|
|
302
263
|
isValid: false,
|
303
264
|
errors: false,
|
304
265
|
});
|
305
|
-
|
266
|
+
useIsomorphicLayoutEffect(() => control._subscribe({
|
306
267
|
name: name,
|
307
268
|
formState: _localProxyFormState.current,
|
308
269
|
exact,
|
@@ -314,10 +275,10 @@ function useFormState(props) {
|
|
314
275
|
});
|
315
276
|
},
|
316
277
|
}), [name, disabled, exact]);
|
317
|
-
|
278
|
+
React__default.useEffect(() => {
|
318
279
|
_localProxyFormState.current.isValid && control._setValid(true);
|
319
280
|
}, [control]);
|
320
|
-
return
|
281
|
+
return React__default.useMemo(() => getProxyFormState(formState, control, _localProxyFormState.current, false), [formState, control]);
|
321
282
|
}
|
322
283
|
|
323
284
|
var isString = (value) => typeof value === 'string';
|
@@ -353,17 +314,18 @@ var generateWatchOutput = (names, _names, formValues, isGlobal, defaultValue) =>
|
|
353
314
|
function useWatch(props) {
|
354
315
|
const methods = useFormContext();
|
355
316
|
const { control = methods.control, name, defaultValue, disabled, exact, } = props || {};
|
356
|
-
const
|
357
|
-
|
317
|
+
const _defaultValue = React__default.useRef(defaultValue);
|
318
|
+
const [value, updateValue] = React__default.useState(control._getWatch(name, _defaultValue.current));
|
319
|
+
useIsomorphicLayoutEffect(() => control._subscribe({
|
358
320
|
name: name,
|
359
321
|
formState: {
|
360
322
|
values: true,
|
361
323
|
},
|
362
324
|
exact,
|
363
325
|
callback: (formState) => !disabled &&
|
364
|
-
updateValue(generateWatchOutput(name, control._names, formState.values || control._formValues, false,
|
365
|
-
}), [name,
|
366
|
-
|
326
|
+
updateValue(generateWatchOutput(name, control._names, formState.values || control._formValues, false, _defaultValue.current)),
|
327
|
+
}), [name, control, disabled, exact]);
|
328
|
+
React__default.useEffect(() => control._removeUnmounted());
|
367
329
|
return value;
|
368
330
|
}
|
369
331
|
|
@@ -406,13 +368,13 @@ function useController(props) {
|
|
406
368
|
name,
|
407
369
|
exact: true,
|
408
370
|
});
|
409
|
-
const _props =
|
410
|
-
const _registerProps =
|
371
|
+
const _props = React__default.useRef(props);
|
372
|
+
const _registerProps = React__default.useRef(control.register(name, {
|
411
373
|
...props.rules,
|
412
374
|
value,
|
413
375
|
...(isBoolean(props.disabled) ? { disabled: props.disabled } : {}),
|
414
376
|
}));
|
415
|
-
const fieldState =
|
377
|
+
const fieldState = React__default.useMemo(() => Object.defineProperties({}, {
|
416
378
|
invalid: {
|
417
379
|
enumerable: true,
|
418
380
|
get: () => !!get(formState.errors, name),
|
@@ -434,32 +396,27 @@ function useController(props) {
|
|
434
396
|
get: () => get(formState.errors, name),
|
435
397
|
},
|
436
398
|
}), [formState, name]);
|
437
|
-
const onChange =
|
399
|
+
const onChange = React__default.useCallback((event) => _registerProps.current.onChange({
|
438
400
|
target: {
|
439
401
|
value: getEventValue(event),
|
440
402
|
name: name,
|
441
403
|
},
|
442
404
|
type: EVENTS.CHANGE,
|
443
405
|
}), [name]);
|
444
|
-
const onBlur =
|
406
|
+
const onBlur = React__default.useCallback(() => _registerProps.current.onBlur({
|
445
407
|
target: {
|
446
408
|
value: get(control._formValues, name),
|
447
409
|
name: name,
|
448
410
|
},
|
449
411
|
type: EVENTS.BLUR,
|
450
412
|
}), [name, control._formValues]);
|
451
|
-
const ref =
|
413
|
+
const ref = React__default.useCallback((elm) => {
|
452
414
|
const field = get(control._fields, name);
|
453
415
|
if (field && elm) {
|
454
|
-
field._f.ref =
|
455
|
-
focus: () => elm.focus(),
|
456
|
-
select: () => elm.select(),
|
457
|
-
setCustomValidity: (message) => elm.setCustomValidity(message),
|
458
|
-
reportValidity: () => elm.reportValidity(),
|
459
|
-
};
|
416
|
+
field._f.ref = elm;
|
460
417
|
}
|
461
418
|
}, [control._fields, name]);
|
462
|
-
const field =
|
419
|
+
const field = React__default.useMemo(() => ({
|
463
420
|
name,
|
464
421
|
value,
|
465
422
|
...(isBoolean(disabled) || formState.disabled
|
@@ -469,7 +426,7 @@ function useController(props) {
|
|
469
426
|
onBlur,
|
470
427
|
ref,
|
471
428
|
}), [name, disabled, formState.disabled, onChange, onBlur, ref, value]);
|
472
|
-
|
429
|
+
React__default.useEffect(() => {
|
473
430
|
const _shouldUnregisterField = control._options.shouldUnregister || shouldUnregister;
|
474
431
|
control.register(name, {
|
475
432
|
..._props.current.rules,
|
@@ -500,13 +457,13 @@ function useController(props) {
|
|
500
457
|
: updateMounted(name, false);
|
501
458
|
};
|
502
459
|
}, [name, control, isArrayField, shouldUnregister]);
|
503
|
-
|
460
|
+
React__default.useEffect(() => {
|
504
461
|
control._setDisabledField({
|
505
462
|
disabled,
|
506
463
|
name,
|
507
464
|
});
|
508
465
|
}, [disabled, name, control]);
|
509
|
-
return
|
466
|
+
return React__default.useMemo(() => ({
|
510
467
|
field,
|
511
468
|
formState,
|
512
469
|
fieldState,
|
@@ -598,7 +555,7 @@ const POST_REQUEST = 'post';
|
|
598
555
|
*/
|
599
556
|
function Form(props) {
|
600
557
|
const methods = useFormContext();
|
601
|
-
const [mounted, setMounted] =
|
558
|
+
const [mounted, setMounted] = React__default.useState(false);
|
602
559
|
const { control = methods.control, onSubmit, children, action, method = POST_REQUEST, headers, encType, onError, render, onSuccess, validateStatus, ...rest } = props;
|
603
560
|
const submit = async (event) => {
|
604
561
|
let hasError = false;
|
@@ -664,12 +621,12 @@ function Form(props) {
|
|
664
621
|
});
|
665
622
|
}
|
666
623
|
};
|
667
|
-
|
624
|
+
React__default.useEffect(() => {
|
668
625
|
setMounted(true);
|
669
626
|
}, []);
|
670
|
-
return render ? (
|
627
|
+
return render ? (React__default.createElement(React__default.Fragment, null, render({
|
671
628
|
submit,
|
672
|
-
}))) : (
|
629
|
+
}))) : (React__default.createElement("form", { noValidate: mounted, action: action, method: method, encType: encType, onSubmit: submit, ...rest }, children));
|
673
630
|
}
|
674
631
|
|
675
632
|
var appendErrors = (name, validateAllFieldCriteria, errors, type, message) => validateAllFieldCriteria
|
@@ -712,6 +669,39 @@ var createSubject = () => {
|
|
712
669
|
};
|
713
670
|
};
|
714
671
|
|
672
|
+
var isPrimitive = (value) => isNullOrUndefined(value) || !isObjectType(value);
|
673
|
+
|
674
|
+
function deepEqual(object1, object2) {
|
675
|
+
if (isPrimitive(object1) || isPrimitive(object2)) {
|
676
|
+
return object1 === object2;
|
677
|
+
}
|
678
|
+
if (isDateObject(object1) && isDateObject(object2)) {
|
679
|
+
return object1.getTime() === object2.getTime();
|
680
|
+
}
|
681
|
+
const keys1 = Object.keys(object1);
|
682
|
+
const keys2 = Object.keys(object2);
|
683
|
+
if (keys1.length !== keys2.length) {
|
684
|
+
return false;
|
685
|
+
}
|
686
|
+
for (const key of keys1) {
|
687
|
+
const val1 = object1[key];
|
688
|
+
if (!keys2.includes(key)) {
|
689
|
+
return false;
|
690
|
+
}
|
691
|
+
if (key !== 'ref') {
|
692
|
+
const val2 = object2[key];
|
693
|
+
if ((isDateObject(val1) && isDateObject(val2)) ||
|
694
|
+
(isObject(val1) && isObject(val2)) ||
|
695
|
+
(Array.isArray(val1) && Array.isArray(val2))
|
696
|
+
? !deepEqual(val1, val2)
|
697
|
+
: val1 !== val2) {
|
698
|
+
return false;
|
699
|
+
}
|
700
|
+
}
|
701
|
+
}
|
702
|
+
return true;
|
703
|
+
}
|
704
|
+
|
715
705
|
var isEmptyObject = (value) => isObject(value) && !Object.keys(value).length;
|
716
706
|
|
717
707
|
var isFileInput = (element) => element.type === 'file';
|
@@ -1275,7 +1265,7 @@ function createFormControl(props = {}) {
|
|
1275
1265
|
};
|
1276
1266
|
const _fields = {};
|
1277
1267
|
let _defaultValues = isObject(_options.defaultValues) || isObject(_options.values)
|
1278
|
-
? cloneObject(_options.
|
1268
|
+
? cloneObject(_options.defaultValues || _options.values) || {}
|
1279
1269
|
: {};
|
1280
1270
|
let _formValues = _options.shouldUnregister
|
1281
1271
|
? {}
|
@@ -2386,17 +2376,17 @@ var updateAt = (fieldValues, index, value) => {
|
|
2386
2376
|
function useFieldArray(props) {
|
2387
2377
|
const methods = useFormContext();
|
2388
2378
|
const { control = methods.control, name, keyName = 'id', shouldUnregister, rules, } = props;
|
2389
|
-
const [fields, setFields] =
|
2390
|
-
const ids =
|
2391
|
-
const _fieldIds =
|
2392
|
-
const _name =
|
2393
|
-
const _actioned =
|
2379
|
+
const [fields, setFields] = React__default.useState(control._getFieldArray(name));
|
2380
|
+
const ids = React__default.useRef(control._getFieldArray(name).map(generateId));
|
2381
|
+
const _fieldIds = React__default.useRef(fields);
|
2382
|
+
const _name = React__default.useRef(name);
|
2383
|
+
const _actioned = React__default.useRef(false);
|
2394
2384
|
_name.current = name;
|
2395
2385
|
_fieldIds.current = fields;
|
2396
2386
|
control._names.array.add(name);
|
2397
2387
|
rules &&
|
2398
2388
|
control.register(name, rules);
|
2399
|
-
|
2389
|
+
React__default.useEffect(() => control._subjects.array.subscribe({
|
2400
2390
|
next: ({ values, name: fieldArrayName, }) => {
|
2401
2391
|
if (fieldArrayName === _name.current || !fieldArrayName) {
|
2402
2392
|
const fieldValues = get(values, _name.current);
|
@@ -2407,7 +2397,7 @@ function useFieldArray(props) {
|
|
2407
2397
|
}
|
2408
2398
|
},
|
2409
2399
|
}).unsubscribe, [control]);
|
2410
|
-
const updateValues =
|
2400
|
+
const updateValues = React__default.useCallback((updatedFieldArrayValues) => {
|
2411
2401
|
_actioned.current = true;
|
2412
2402
|
control._setFieldArray(name, updatedFieldArrayValues);
|
2413
2403
|
}, [control, name]);
|
@@ -2496,7 +2486,7 @@ function useFieldArray(props) {
|
|
2496
2486
|
setFields([...updatedFieldArrayValues]);
|
2497
2487
|
control._setFieldArray(name, [...updatedFieldArrayValues], (data) => data, {}, true, false);
|
2498
2488
|
};
|
2499
|
-
|
2489
|
+
React__default.useEffect(() => {
|
2500
2490
|
control._state.action = false;
|
2501
2491
|
isWatched(name, control._names) &&
|
2502
2492
|
control._subjects.state.next({
|
@@ -2556,7 +2546,7 @@ function useFieldArray(props) {
|
|
2556
2546
|
control._setValid();
|
2557
2547
|
_actioned.current = false;
|
2558
2548
|
}, [fields, name, control]);
|
2559
|
-
|
2549
|
+
React__default.useEffect(() => {
|
2560
2550
|
!get(control._formValues, name) && control._setFieldArray(name);
|
2561
2551
|
return () => {
|
2562
2552
|
const updateMounted = (name, value) => {
|
@@ -2571,22 +2561,21 @@ function useFieldArray(props) {
|
|
2571
2561
|
};
|
2572
2562
|
}, [name, control, keyName, shouldUnregister]);
|
2573
2563
|
return {
|
2574
|
-
swap:
|
2575
|
-
move:
|
2576
|
-
prepend:
|
2577
|
-
append:
|
2578
|
-
remove:
|
2579
|
-
insert:
|
2580
|
-
update:
|
2581
|
-
replace:
|
2582
|
-
fields:
|
2564
|
+
swap: React__default.useCallback(swap, [updateValues, name, control]),
|
2565
|
+
move: React__default.useCallback(move, [updateValues, name, control]),
|
2566
|
+
prepend: React__default.useCallback(prepend, [updateValues, name, control]),
|
2567
|
+
append: React__default.useCallback(append, [updateValues, name, control]),
|
2568
|
+
remove: React__default.useCallback(remove, [updateValues, name, control]),
|
2569
|
+
insert: React__default.useCallback(insert$1, [updateValues, name, control]),
|
2570
|
+
update: React__default.useCallback(update, [updateValues, name, control]),
|
2571
|
+
replace: React__default.useCallback(replace, [updateValues, name, control]),
|
2572
|
+
fields: React__default.useMemo(() => fields.map((field, index) => ({
|
2583
2573
|
...field,
|
2584
2574
|
[keyName]: ids.current[index] || generateId(),
|
2585
2575
|
})), [fields, keyName]),
|
2586
2576
|
};
|
2587
2577
|
}
|
2588
2578
|
|
2589
|
-
const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
|
2590
2579
|
/**
|
2591
2580
|
* Custom hook to manage the entire form.
|
2592
2581
|
*
|
@@ -2617,9 +2606,9 @@ const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? React.useLayou
|
|
2617
2606
|
* ```
|
2618
2607
|
*/
|
2619
2608
|
function useForm(props = {}) {
|
2620
|
-
const _formControl =
|
2621
|
-
const _values =
|
2622
|
-
const [formState, updateFormState] =
|
2609
|
+
const _formControl = React__default.useRef(undefined);
|
2610
|
+
const _values = React__default.useRef(undefined);
|
2611
|
+
const [formState, updateFormState] = React__default.useState({
|
2623
2612
|
isDirty: false,
|
2624
2613
|
isValidating: false,
|
2625
2614
|
isLoading: isFunction(props.defaultValues),
|
@@ -2661,10 +2650,11 @@ function useForm(props = {}) {
|
|
2661
2650
|
...data,
|
2662
2651
|
isReady: true,
|
2663
2652
|
}));
|
2653
|
+
control._formState.isReady = true;
|
2664
2654
|
return sub;
|
2665
2655
|
}, [control]);
|
2666
|
-
|
2667
|
-
|
2656
|
+
React__default.useEffect(() => control._disableForm(props.disabled), [control, props.disabled]);
|
2657
|
+
React__default.useEffect(() => {
|
2668
2658
|
if (props.mode) {
|
2669
2659
|
control._options.mode = props.mode;
|
2670
2660
|
}
|
@@ -2675,13 +2665,13 @@ function useForm(props = {}) {
|
|
2675
2665
|
control._setErrors(props.errors);
|
2676
2666
|
}
|
2677
2667
|
}, [control, props.errors, props.mode, props.reValidateMode]);
|
2678
|
-
|
2668
|
+
React__default.useEffect(() => {
|
2679
2669
|
props.shouldUnregister &&
|
2680
2670
|
control._subjects.state.next({
|
2681
2671
|
values: control._getWatch(),
|
2682
2672
|
});
|
2683
2673
|
}, [control, props.shouldUnregister]);
|
2684
|
-
|
2674
|
+
React__default.useEffect(() => {
|
2685
2675
|
if (control._proxyFormState.isDirty) {
|
2686
2676
|
const isDirty = control._getDirty();
|
2687
2677
|
if (isDirty !== formState.isDirty) {
|
@@ -2691,7 +2681,7 @@ function useForm(props = {}) {
|
|
2691
2681
|
}
|
2692
2682
|
}
|
2693
2683
|
}, [control, formState.isDirty]);
|
2694
|
-
|
2684
|
+
React__default.useEffect(() => {
|
2695
2685
|
if (props.values && !deepEqual(props.values, _values.current)) {
|
2696
2686
|
control._reset(props.values, control._options.resetOptions);
|
2697
2687
|
_values.current = props.values;
|
@@ -2701,7 +2691,7 @@ function useForm(props = {}) {
|
|
2701
2691
|
control._resetDefaultValues();
|
2702
2692
|
}
|
2703
2693
|
}, [control, props.values]);
|
2704
|
-
|
2694
|
+
React__default.useEffect(() => {
|
2705
2695
|
if (!control._state.mount) {
|
2706
2696
|
control._setValid();
|
2707
2697
|
control._state.mount = true;
|